使用spring-boot配置aop会变得十分简单,只需引入一个starter即可,但是也有需要注意的地方,以下记录一下踩的坑。
首先是配置方式:
maven依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependencies>
引入web的starter和aop的starter即可。
然后就可以配置切面了,这里配置一个简单的类测试Aop的功能(实现了Act接口):
@Component
public class AopAct implements Act{
@Override
public void act(String arg) {
System.out.println(arg);
}
}
申明一个切面,在act方法之前执行一个控制台输出:
@Component
@Aspect
public class AopConfig {
@Before("execution(public void lx.test.aop.AopAct.act(..)) && args(arg)")
public void beforeAct(String arg) {
System.out.println("before...");
}
}
按照常理来说,这个类由于实现了一个接口,由spring处理时会默认使用JDK的代理来实现AOP,但是代码跑起来却不是,debug模式查看Act类的类型,发现是
cglib代理类,这是怎么回事呢?工程中也没有通过注解 @EnableAspectJAutoProxy上配置(proxyTargetClass = true) 来开启cglib代理。
后来发现spring-boot-aop-starter引入aop的依赖配置时候,通过spring.factories引入了一个类AopAutoConfiguration,这个类会自动配置proxyTargetClass = true,使得代理类强制通过cglib代理。
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Advice.class)
static class AspectJAutoProxyingConfiguration {
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
matchIfMissing = false)
static class JdkDynamicAutoProxyConfiguration {
}
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = true)
//这里的配置使得默认会注入proxyTargetClass属性,使spring使用cglib生成代理类
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class CglibAutoProxyConfiguration {
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class ClassProxyingConfiguration {
ClassProxyingConfiguration(BeanFactory beanFactory) {
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
}
}
}
在aop-starter的配置下,使用注解@EnableAspectJAutoProxy(proxyTargetClass = false)的申明是无效的,需要在配置文件进行配置:
spring.aop.auto=true
#false 开启jdk代理,true则强制使用cglib代理
spring.aop.proxy-target-class=false