之前我们自定义一个AOP时,都需要添加 @EnableAspectJAutoProxy
,但是为何在SpringBoot项目中,我们只需要引入依赖就可以完整自动的配置呢?
因为AOP的自动配置类帮我们开启了
为何会自动开启呢?在EnableAutoConfiguration 源码分析时,我们说过这样一段代码,也是Spring源码中经常用到的;
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
if (result != null) {
return result;
} else {
try {
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
LinkedMultiValueMap result = new LinkedMultiValueMap();
......
cache.put(classLoader, result);
return result;
} catch (IOException var13) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
}
}
}
其实它是将spring.factories
文件中的key存放在List中,而在这里您会发现,如下的配置
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,
也就是说Spring启动时会,自动将AopAutoConfiguration
注入到容器中,那我们看一下AopAutoConfiguration
的源码,他做了写什么
@Configuration(proxyBeanMethods = false)
//解析spring.aop.auto=true属性 加载aspect配置
@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)
//spring.aop.proxy-target-class = false 采用jdk动态代理
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
matchIfMissing = false)
static class JdkDynamicAutoProxyConfiguration {
}
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = true)
// spring.aop.proxy-target-class = true 采用cglib动态代理
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class CglibAutoProxyConfiguration {
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
// spring.aop.proxy-target-class = true 开启动态代理
@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);
}
}
}
}
说明:
@ConditionalOnClass(Advice.class) –> 在当前的类路径下存在EnableAspectJAutoProxy.class, Aspect.class, Advice.class时该配置才被解析 @ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true) –> 当配置有spring.aop.auto= true时生效.如果没有配置,则默认生效
因此,我们可以知道,aop 默认使用的是Cglib代理,Spring官方是这样说的
Whether subclass-based (CGLIB) proxies are to be created (true), as opposed to standard Java interface-based proxies (false).
这是针对于spring.aop.proxy-target-class
的配置进行说明的,如果您想使用JDK代理,只需要修改默认的配置即可