开始面向切面
术语:
advice:切面要完成的工作称为advice
advice不只是定义了去做什么,还要定义什么时候去做。
有5中时刻:- before:在方法执行前
- after:方法执行完。不管是正常退出,还是抛异常了。
- after-returning:方法正常执行完。
- after-throwing:方法抛异常时。
- around:可指定方法的插入时机
join point:
顾名思义,切入点。切面在何处切入。这个切入点可以是方法被调用。异常抛出,或者是修改变量时。一群候选的等待切入的点。pointCut
这是一个匹配操作。我们通过advice定义了做什么和什么时候做。通过joinpoint定义了在哪里做。然后我们定义pointCut确定具体是哪个类哪个方法,或者抛什么异常的时候去做。pointcut选择具体的一个joinpoint去join。aspect:
advice 和pointcut的和。什么时候什么地方去做什么。introductions
引入。意思是使用aop,可以给已存在的类,引入新的变量和方法。weaving
织入,就是指我们对具体某个对象进行aop,织入advice,组成了一个新的混合原对象和advice的代理类。有三种织入时机:- 编译时。这需要特殊的编译器。AspectJ的可以。
- 加载时。这需要特殊的类加载器。AspectJ 5的可以。
- 运行时。这是Spring AOP的织入时机,创建动态代理类。
aop
有多种aop框架,功能不同,主要看织入的粒度,著名的是spring aop和aspectJ。只要能完成何时何地织入何物就是一个aop。spring aop和aspectJ协作良好。
spring aop是基于动态代理的。所以限制了spring aop只能方法级别的织入。aspectJ和Jboss更高级一点,支持field和构造器的织入。
spring使用aspectJ的写法去定义切面
里面最重要的是execution(),其他的都是limite作用。
使用execution的例子:
concert.Performance.perform是一个具体的方法
* : 任意返回值
.. : 任意参数类型和个数
然后,比如想限定只切入concert包下的方法:
可以用上表中的within
使用&&连接,也可以用||和!
等于直接用and or not 字符串
除了上表,spring提供了bean()限定,具体的beanID
这个限定了除了id是woodstock的bean。
如何定义一个aspect。实例:
每一个方法的execution都是一样的,我们可以使用@Pointcut定义一个可重复使用的pointCut。
注意performance()方法应该是个空方法。
到目前为止,我们定义好了aspect。但是spring并不会自动为match上的方法执行织入。必须开启spring的自动代理。
开启方法:
javaconfig:@EnableAspectJAutoProxy
xml:<aop:aspectj-autoproxy />
这样spring才能很具aspect自动创建代理类
详解around advice
5中advice是个中最复杂的就是around了。
与其他几个不同之处是,@Around注解的方法是有参数的。ProceedingJoinPoint
在advice中传参
前面说的@Pointcut定义的方法,应该是空方法体,但是他是可以传参数的。
introduction引入
前面都是用aop在已有的方法基础上增加功能。
我们可以使用introduction给beans增加不存在的方法。
看这张图,spring的aop采取的方法并不是真的在你的bean里添加方法。而是构造一个新的类,实现新的方法,然后与你的bean组合成一个新的代理。
具体代码:
使用@DeclareParents注解,参数value表示要和实现那些接口的类混合。
defaultImpl:你自己的实现类
还要在application context中声明这个bean
<bean class="concert.EncoreableIntroducer" />
这样spring才能找到,并开始作为aspect对待他。
在XML中配置aop
如果你拿不到源码,那么你必须用xml配置了。
将上面的javaconfig示例转换为xml配置:
其他对应的功能,都可以在xml中配置实现。