-
AOP concepts
- Aspect:切面
- Join point:织入点
- Advice:建议
- Pointcut:织入点的集合
- Target object:目标对象
- AOP proxy:代理对象
- Weaving:编织
-
@AspectJ or XML for Spring AOP?
Spring对AOP的配置,可以选择XML或者是注解。
采用注解形式,Spring提供类似AspectJ的语法(但内部还是Spring自己的实现,没有依赖AspectJ的实现)。采用XML,Spring提供了自己的配置语法。
-
@AspectJ support
如果采用注解形式的配置需要在Spring的配置文件里面加上下面这句话。
<aop:aspectj-autoproxy/>
这样,Spring在初始化bean的时候,就能扫描到关于AOP的相应的注解了。
在这里就不赘述一些配置和织入点语法,详细内容可见官方文档。下面是一个小Demo
<context:annotation-config/>
<aop:aspectj-autoproxy/>
<bean id = "al" class = "com.jiakai.aspect.LogAspect" />
<bean id = "car" class = "com.jiakai.model.Car" />
package com.jiakai.aspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class LogAspect {
@Before(value="execution(* com.jiakai.model.*.*(..))")
public void logBegin(){
System.out.println("log begin");
}
@After(value="execution(* com.jiakai.model.*.*(..))")
public void logfinish(){
System.out.println("log finish");
}
}
package com.jiakai.itfa;
public interface Moveable {
void move();
}
package com.jiakai.model;
import com.jiakai.itfa.Moveable;
public class Car implements Moveable{
@Override
public void move() {
System.out.println("The car go go go........");
}
}
package com.jiakai.model;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.jiakai.itfa.Moveable;
public class Test {
public static void main(String[] args) {
BeanFactory bf = new ClassPathXmlApplicationContext("beans.xml");
System.out.println("-------");
Moveable m = (Moveable)bf.getBean("car");
m.move();
System.out.println(m.getClass().getName());
}
}
结果如下:
-------
log begin
The car go go go........
log finish
$Proxy6
log begin
The car go go go........
log finish
$Proxy6
细心的你,可能已经看见了。此时我们拿到的car并不是com.jiakai.model.Car。而是一个代理对象(由JDK Proxy类生成的)。
因为Spring在初始化容器的时候,发现了切面类和织入点。他把切面类的逻辑织入到了car类上,形成了一个代理对象。
此时他会提供给你代理对象(为了实现AOP)。
了解动态代理实现的人都应该知道,如果用JDK自带的Proxy类来实现动态代理的话。
目标对象都需要实现接口,否则会出错。
如果目标对象没有实现接口,那么可以用cglib来实现。
如果想用cglib实现的话,只需更改下面的配置,并导入相应的Jar包。
<aop:aspectj-autoproxy proxy-target-class="true" />
-
Schema-based AOP support
<aop:config>
<!-- ..... -->
</aop:config>
关于AOP的配置都放在这个标签里。
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
<!-- ... -->
</aop:aspect>
</aop:config>
<bean id="aBean" class="...">
<!-- ... -->
</bean>
切面sample
<aop:pointcut expression="" id=""/>
切入点配置可以放在<aop:config> </aop:config> 里面 或者 <aop:aspect></aop:aspect> 里面
前者所有切面都可以用,后者只有所在切面才能使用。
综合使用的Demo
<context:annotation-config />
<bean id="al" class="com.jiakai.aspect.LogAspect" />
<bean id="car" class="com.jiakai.model.Car" />
<aop:config>
<aop:pointcut expression="execution(* com.jiakai.model.*.*(..))" id="alpc"/>
<aop:aspect id="aspect" ref="al" >
<aop:before method="logBegin" pointcut-ref="alpc" />
<aop:after method="logfinish" pointcut="execution(* com.jiakai.model.*.*(..))" />
</aop:aspect>
</aop:config>
package com.jiakai.aspect;
public class LogAspect {
public void logBegin() {
System.out.println("log begin");
}
public void logfinish() {
System.out.println("log finish");
}
}