博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring之AOP二
阅读量:6624 次
发布时间:2019-06-25

本文共 3983 字,大约阅读时间需要 13 分钟。

在Spring之AOP一中使用动态代理将日志打印功能注入到目标对象中,其实这就是AOP实现的原理,不过上面只是Java的实现方式。AOP不管什么语言它的几个主要概念还是有必要了解一下的。

一、AOP概念

1.横切关注点

AOP把一个业务流程分成几部分,例如权限检查、业务处理、日志记录,每个部分单独处理,然后把它们组装成完整的业务流,每部分被称为切面或关注点。

2.切面

类是对物体特征的抽象,切面就是对横切关注点的抽象。可以每部分抽象成一叠纸一样一层一层的,那每张纸都是一切面。

3.连接点

被拦截到的点,我看有的博客说:因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器.其实我觉得Spring只支持方法类型的连接点就包含字段和构造器。为啥呢?因为字段它是通过get,set方法,构造器它其实也是方法。Spring只支持方法类型的连接点和连接点是字段或者构造器它们是包含关系。

4.切入点

对连接点进行拦截的定义,连接点可以很多,但并不一定每个连接点都进行操作,比如莲藕,藕段与藕段之间它们是有连接点的,但不一定都切开。

5.通知

通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类,这个呢就是把藕段与藕段断开之后要做的事情,是往里面加蜂蜜还是做什么。

6.目标对象

代理的目标对象,就是上一博客动态代理的target,在实际操作中一般会先实现AOP的接口,然后配置这些接口作用到哪些对象上,被作用的对象就是目标对象。

7.织入

切面是独立的,目标对象也是独立的,它们是不耦合的,那它怎么把切面放到目标对象中呢,这时就需要进行织入操作,就类似一中的,怎么把target和打印日志联系到一起呢,那就需要动态代理,在spring中aop.framework.ProxyFactory就是用作织入器,来进行横切逻辑的织入。

8.引入

 不改代码的同时,为类动态的添加方法或字段。

二、AOP配置

AOP配置元素 描述
<aop:config> 顶层的AOP配置元素,大多数的<aop:*>元素必须包含在<aop:config>元素内
<aop:aspect> 定义切面
<aop:aspect-autoproxy> 启用@AspectJ注解驱动的切面
<aop:pointcut> 定义切点
<aop:advisor> 定义AOP通知器
<aop:before> 定义AOP前置通知
<aop:after> 定义AOP后置通知(不管被通知的方法是否执行成功)
<aop:after-returning> 定义成功返回后的通知
<aop:after-throwing> 定义抛出异常后的通知
<aop:around> 定义AOP环绕通知
<aop:declare-parents> 为被通知的对象引入额外的接口,并透明地实现

三、实现

1.pom.xml引入aspectjweaver.jar、aspectjrt.jar

aspectj
aspectjweaver
1.5.4
aspectj
aspectjrt
1.5.4
View Code

2.定义切面类

package Cuiyw.Spring.Service;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;public class ServiceAspect {    public void beforeAdvice() {        System.out.println("前置通知执行了");    }    public void afterAdvice() {        System.out.println("后置通知执行了");    }    public void afterReturnAdvice(String result) {        System.out.println("返回通知执行了" + "运行业务方法返回的结果为" + result);    }    public String aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {        String result = "";        try {            System.out.println("环绕通知开始执行了");            long start = System.currentTimeMillis();            result = (String) proceedingJoinPoint.proceed();            long end = System.currentTimeMillis();            System.out.println("环绕通知执行结束了");            System.out.println("执行业务方法共计:" + (end - start) + "毫秒。");        } catch (Throwable e) {        }        return result;    }    public void throwingAdvice(JoinPoint joinPoint, Exception e) {        StringBuffer stringBuffer = new StringBuffer();        stringBuffer.append("异常通知执行了.");        stringBuffer.append("方法:").append(joinPoint.getSignature().getName()).append("出现了异常.");        stringBuffer.append("异常信息为:").append(e.getMessage());        System.out.println(stringBuffer.toString());    }}
View Code

3.上下文中定义切面、切点

View Code

4.在main中调用service

ApplicationContext context=new ClassPathXmlApplicationContext(new String[]{"ApplicationContext.xml"});        BeanFactory factory=context;        IService serviceImplA1=(IService)factory.getBean("serviceImplA");        serviceImplA1.service("Cuiyw ServiceA");
View Code

5.错误

ServiceImplA serviceImplA2=factory.getBean("serviceImplA",ServiceImplA.class);        serviceImplA2.service("Cuiyw ServiceA");
View Code

使用上面的代码来测试出现下面的错误,使用4中接口的方式就可以,这个是参考http://blog.csdn.net/two_people/article/details/51816964中的

Bean named 'serviceImplA' is expected to be of type 'Cuiyw.Spring.Service.ServiceImplA' but was actually of type 'com.sun.proxy.$Proxy4'
View Code

四、总结

上面演示了AOP的实现方式,其实还有多种方式实现,这里只写了一个demo。还有3个小时就到2018了,祝大家新年快乐!

五、补充

最近在回头整理Spring相关方面的知识,在写demo的时候,按照上面的来重新配置居然报错了,之前是可以运行成功的,百度了好久也是没找到原因,后来想着重新写,参考网上了例子,更改了下aspectjweaver、aopalliance版本号居然可以了。

你可能感兴趣的文章
asp.net 父窗体获取子窗体的返回值,可用来对父窗体局部更新
查看>>
.Net下使用 Geb.Video.FFMPEG 操作视频文件
查看>>
OpenGL入门笔记(十四)
查看>>
秒懂C#通过Emit动态生成代码
查看>>
redis主从复制,读写分离
查看>>
Routing Error uninitialized constant TransController
查看>>
设计模式(二): BUILDER生成器模式 -- 创建型模式
查看>>
git: No refs in common and none specified; doing no
查看>>
I.MX6 天嵌 E9 U-boot menu hacking
查看>>
Eclipse中Android项目引用其他项目时链接源码的方法
查看>>
Mac PD虚拟机卸载删除
查看>>
java中String、StringBuffer、StringBuilder的区别
查看>>
EL 表达式
查看>>
WPF水珠效果按钮组
查看>>
一个不错的命令行解析类
查看>>
I.MX6 FFmpeg 录制视频
查看>>
phpstudy 安装选择,iis+php组合,如何设置伪静态
查看>>
EMF介绍系列(六、自定义命令)
查看>>
基于DFA敏感词查询的算法简析
查看>>
设置mysql远程连接root权限
查看>>