Springboot中的AOP
Springboot开发,发现同事使用切面的时候并未添加@EnableAspectJAutoProxy注解,本人产生了一些疑惑,记得当时看源码的时候,这个注解是必须加的。思索了一会,发现当时使用的是SpringAOP,并未引入Springboot,那么问题在springboot的autoconfigure上了,随后翻了下源码,解决了这个小疑惑。
关于SprongAop的原理,可以看SpringAOP
最简单的想法是直接在idea中搜aop、autoConfiguration等关键字,最后找到了以下代码
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")
static class JdkDynamicAutoProxyConfiguration {
}
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class CglibAutoProxyConfiguration {
}
可以看到,默认是开启了CGLib代理,但是没有设置暴露代理对象,如有需求,需手动加入@EnableAspectJAutoProxy,并设置exposeProxy为true
下面还有一段代码
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class ClassProxyingConfiguration {
@Bean
static BeanFactoryPostProcessor forceAutoProxyCreatorToUseClassProxying() {
return (beanFactory) -> {
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
};
}
}
但是项目中引入了org.aspectj.weaver.Advice,按道理这个bean不会被注入,之后下了断点,也确实没断下来,说明这不是自动配置的地方。
不过也让我复习了BeanFactoryPostProcessor,这里要使用@Bean才能成功注入。
其实不仅aop是如此配置的,springboot事务也是非常相似的配置
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(TransactionManager.class)
@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
public static class EnableTransactionManagementConfiguration {
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")
public static class JdkDynamicAutoProxyConfiguration {
}
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
public static class CglibAutoProxyConfiguration {
}
}
我们也不需要手动添加@EnableTrasactionManagement注解了,在这个注解中,其实还是向实现了@EnableAspectJAutoProxy的功能
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
Q.E.D.