1.概述
springboot声明式事务是通过动态代理实现的,本文通过@EnableTransactionManagement做为入口,跟踪spring代理的开启过程;
2.结论(重点)
开启动态代理的功能就是引入动态代理创建器的bean定义(@EnableTransactionManagement引入InfrastructureAdvisorAutoProxyCreator)。动态代理创建器负责生成代理对象的动态代理,增强代理对象;
3.原理
实现方式
spring声明式事务使用动态代理实现,实现有三种方式:
- 如果类实现了接口,使用jdk提供的动态代理(默认);
- 如果类没有实现接口,使用第三方库cglib,在运行时动态生成Java类的子类;
- 使用AspectJ代理,在编译阶段生成AOP代理类,并将织入到Java字节码中。也称为静态代理;
开启过程
@EnableTransactionManagement
使用@Import引入TransactionManagementConfigurationSelector;
TransactionManagementConfigurationSelector
默认的代理模式为PROXY,TransactionManagementConfigurationSelector的selectImports方法引入AutoProxyRegistrar和ProxyTransactionManagementConfiguration。AutoProxyRegistrar负责生成类的动态代理,其它通过动态代理实现有注解同样会引入AutoProxyRegistrar。比如@EnableCaching。ProxyTransactionManagementConfiguration为动态代理事务相关的配置;
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
//**引入AutoProxyRegistrar和ProxyTransactionManagementConfiguration
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
AutoProxyRegistrar
负责注册动态代理相关的bean定义(InfrastructureAdvisorAutoProxyCreator)。如果启用了CGLIB(proxyTargetClass=true)代理,在代理bean定义中添加属性proxyTargetClass=true;
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
//**获取@EnableTransactionManagement注册所在类的所有注解(一般都是项目的启动类SpringdemoApplication)
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (candidate == null) {
continue;
}
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
//**获取需启用动态代理的注解
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
//**注册动态代理的bean定义(InfrastructureAdvisorAutoProxyCreator)
if (mode == AdviceMode.PROXY) {
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
//**如果启用了CGLIB(proxyTargetClass=true),在代理bean定义中添加属性(definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);)
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
...
}
AopConfigUtils.registerAutoProxyCreatorIfNecessary
注册动态代理的bean定义InfrastructureAdvisorAutoProxyCreator。InfrastructureAdvisorAutoProxyCreator是基础设施自动代理创建器,只考虑基础设施(role=BeanDefinition.ROLE_INFRASTRUCTURE)的Advisor(Advisor:顾问,动态代理额外执行逻辑的抽象),不考虑自定义的Advisor;
- BeanDefinition的role有三种类型:
- ROLE_APPLICATION:表示这个Bean是用户自己定义的Bean,最常用的角色类型;
- ROLE_SUPPORT:表示这个Bean是某些复杂配置的支撑部分。通常用于支持其他Bean的配置,例如一些中间件或者服务。
- ROLE_INFRASTRUCTURE:表示这是一个Spring内部的Bean。通常用于实现Spring框架的核心功能,例如数据源、事务管理器等;
- InfrastructureAdvisorAutoProxyCreator的作用
- 创建代理对象,增强目标对象的功能。InfrastructureAdvisorAutoProxyCreator利用后置处理器机制,在对象创建以后,包装对象并返回代理对象。同时,通过拦截器链对代理对象执行的方法进行调用。
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
//**注册动态代理的bean定义InfrastructureAdvisorAutoProxyCreator
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
//*获取动态代理的bean定义(名称为org.springframework.aop.config.internalAutoProxyCreator)
//**如果当前的动态代理的bean定义不是InfrastructureAdvisorAutoProxyCreator,则根据优先级设置bean定义;
//**InfrastructureAdvisorAutoProxyCreator优先级最低,并且没有提供修改优先级的方法;
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
//**动态代理bean的优先顺序,InfrastructureAdvisorAutoProxyCreator优先级最低
static {
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}
4.默认配置
实际上项目中通常是使用AnnotationAwareAspectJAutoProxyCreator创建cglib动态代理。因为spring有配置类AopAutoConfiguration,使用@EnableAspectJAutoProxy引入AnnotationAwareAspectJAutoProxyCreator,并默认proxyTargetClass=true;
- 只要没有明确配置spring.aop.auto=false,就会使用AnnotationAwareAspectJAutoProxyCreator;
- 只要没有明确配置spring.aop.proxy-target-class=false,就会使用cglib动态代理;
@AutoConfiguration
@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")
static class JdkDynamicAutoProxyConfiguration {
}
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class CglibAutoProxyConfiguration {
}
}
}
如果在声明式事务中想使用InfrastructureAdvisorAutoProxyCreator创建jdk动态代理,需加入以下配置;
spring.aop.auto=false
spring.aop.proxy-target-class=false