Spring框架通过注解配置AOP是基于AspectJ实现的。
Spring框架只是直接使用了AspectJ的注解,但并没有使用AspectJ的编译器或织入器,仍然是在运行时动态生成AOP代理。
aspectj使用的是静态代理,而Spring AOP使用的则是动态代理,当一个实现了接口时,使用JDK动态代理,没有实现接口时,使用cglib动态代理。
1.实例化Bean
可以通过注解或者配置xml的方式。
2.在Spring配置文件中,开启AspectJ注解
首先还是导入jar包
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 开启aspectj注解 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
该标签有两个属性,分别是proxy-target-class和expose-proxy。
- proxy-target-class:如果为true,表示使用cglib生成代理对象。默认为false,表示根据目标类是否实现接口来选择使用JDK动态代理还是cglib代理。
- expose-proxy:是否将代理对象置于ThreadLocal中,默认为false,如果设为true,则表示可以通过AopContext,currentProxy()静态方法获取当前代理对象。
配置<aop:aspectj-autoproxy>后,Spring会根据Bean上的注解来判断一个Bean是否使用切面,然后自动生成对应的AOP代理以拦截其方法调用并添加增强。
3.在增强类上使用注解
public class Book {
public void add() {
System.out.println("add a book");
}
}
@Aspect
public class MyBook {
@Before(value = "execution(* com.codeliu.aop.Book.*(..))")
public void beforeAdd() {
System.out.println("before add a book");
}
}
进行测试
@Test
public void testAop() {
@SuppressWarnings("resource")
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Book book = (Book)context.getBean("book");
book.add();
}
输出
before add a book
add a book
AspectJ使用了下列注解用于配置切面
- @Aspect:配置一个类为切面
- @Before:配置一个方法为前置增强
- @After:配置一个方法为后置增强
- @AfterReturning:配置一个方法为返回时增强
- @AfterThrowing:配置一个方法为抛出异常后增强
- @Around:配置yi个方法为环绕增强
- @DeclareParents:配置一个属性为引介增强