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.


一切很好,不缺烦恼。