六Spring事务--5声明式事务的核心类

六Spring事务--5声明式事务的核心类

6.3 实现声明式事务注解的核心类

事务的配置核心类,主要是实现@EnableTransactionManagement(@EnableXXXXXX等功能)核心的类。这些类用来注册相关的bean。

6.3.1 @EnableTransactionManagement的原理

@EnableTransactionManagement声明在主配置类上,表示开启声明式事务,其原理是通过@Import导入TransactionManagementConfigurationSelector组件,该组件通过selectImport方法,根据返回的字符串集合,决定向spring的beanFactory中导入组件AutoProxyRegistrar和ProxyTransactionManagementConfiguration;

image-20220525175753366

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//导入selector类
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
	//注解参数,标识是否代理targetclass
	boolean proxyTargetClass() default false;
	//增强模式
	AdviceMode mode() default AdviceMode.PROXY;
	//order顺序
	int order() default Ordered.LOWEST_PRECEDENCE;
}

@EnableTransactionManagement注解用@Import导入TransactionManagementConfigurationSelector类

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {
			case PROXY:
        //返回AutoProxyRegistrar和ProxyTransactionManagementConfiguration的类名的字符串数组
				return new String[] {AutoProxyRegistrar.class.getName(),
						ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ:
				return new String[] {determineTransactionAspectClass()};
			default:
				return null;
		}
	}

	private String determineTransactionAspectClass() {
		return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
				TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
				TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
	}

}

这里,通过selectImports方法,获取类名的字符串数组,这里,会向spring导入两个组件类AutoProxyRegistrar和ProxyTransactionManagementConfiguration(@configuration注解的配置类)

image-20221121172237553

selector继承结构如上。

6.3.2 ImportSelector

public interface ImportSelector {

	/**
	 * parm:importingClassMetadata 是@import所注解的类的元数据,如上面EnableTransactionManagement的元数据
	 */
	 //选择并返回需要导入spring的类的名称,基于AnnotationMetadata,并且导入@configuration注解中,导入spring容器
	String[] selectImports(AnnotationMetadata importingClassMetadata);
}

这个方法返回字符串数组,当在配置类中被@import引入,返回的字符串数组中的类名会被spring容器创建。

使用用途:

动态加载特定的类:通过该类,可以做一个类似开关的注解类,通过注解,可以向spring容器中添加selectImports返回的字符串对应的类。

用法:

首先创建实现ImportSelector的类,然后通过@import(selector)添加在配置类@configuration上。然后spring就会把方法返回的字符串,new出对象然后添加入spring的beanFactory中。

public class Dynamic {
    public void say(){
	System.out.println("log for Dynamic");
        return Proxy.newProxyInstance(StaticClassB);//伪码
    }
}

//自定义selector,然后可以自行把dynamic类装载入spring容器
public class MyImportSelect implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{Dynamic.class.getName()};
    }
}

//构造自建的@EnableXXX类,作为开关,可以动态添加selector内的类
@Retention(RetentionPolicy.RUNTIME) //开启运行时加载
@Import(MyImportSelect.class)
public @interface EnableMySelector {
}

//配置类上添加@enable注解,动态添加类
@ComponentScan("com.demo")
@EnableMySelector
public class AppConfig { }


public class Test {
    public static void main(String[] args) {
      //从配置类创建spring容器
        AnnotationConfigApplicationContext anno=newAnnotationConfigApplicationContext(AppConfig.class);
         anno.getBean(Dynamic.class).say();
         }
}
运行打印
log for Dynamic

6.3.2.1 ImportSelector实现原理

ImportSelector类内方法selectImports返回的字符串数组,会在ConfigurationClassParser中被解析,并最终实例化为bean。(parser原理,详细看[2.18 spring.handlers解析标签的原理](#2.18 spring.handlers解析标签的原理))

//parse()方法中调用,省略不看
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
			boolean checkForCircularImports) {

		if (importCandidates.isEmpty()) {
			return;
		}

		if (checkForCircularImports && isChainedImportOnStack(configClass)) {
			this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
		}
		else {
			this.importStack.push(configClass);
			try {
        //import导入的类
				for (SourceClass candidate : importCandidates) {
/**----------------------------------处理ImportSelector的情况-------------------------------------*/
					if (candidate.isAssignable(ImportSelector.class)) {
						// Candidate class is an ImportSelector -> delegate to it to determine imports
						Class<?> candidateClass = candidate.loadClass();
     //实例化当前candidateClass上的ImportSelector类
						ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
								this.environment, this.resourceLoader, this.registry);
						Predicate<String> selectorFilter = selector.getExclusionFilter();
						if (selectorFilter != null) {
							exclusionFilter = exclusionFilter.or(selectorFilter);
						}
          //DeferredImportSelector情况处理(后来很少用到)
						if (selector instanceof DeferredImportSelector) {
							this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
						}
         //ImportSelector情况的处理
						else {
              //调用selectImports方法,得到自定义方法返回需要实例化的类名称
							String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
  /**…………………………………………………………递归调用,处理 selectImports导入的类,也是注册类的情况…………………………………………………………*/
     //获取selectImports内返回的实例类,对于spring事务,就是AutoProxyRegistrar(对应于下面ImportBeanDefinitionRegistrar的处理逻辑)和ProxyTransactionManagementConfiguration(对应于下面configuration类的处理逻辑)
							Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
              //递归调用processImports
							processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
						}
					}
          
/**-----------------------处理ImportBeanDefinitionRegistrar情况---------------------------------*/
					else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
						// Candidate class is an ImportBeanDefinitionRegistrar ->
						// delegate to it to register additional bean definitions
						Class<?> candidateClass = candidate.loadClass();
            //实例化为ImportBeanDefinitionRegistrar类
						ImportBeanDefinitionRegistrar registrar =
								ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
										this.environment, this.resourceLoader, this.registry);
            //添加ImportBeanDefinitionRegistrar到本地缓存
						configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
					}
          
/**-----------------------处理为普通@Configuration注解的类的情况---------------------------------*/
					else {
						// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
						// process it as an @Configuration class
						this.importStack.registerImport(
								currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
            //处理配置类configuration的情况
						processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
					}
				}
			}
			catch (BeanDefinitionStoreException ex) {
				throw ex;
			}
			catch (Throwable ex) {
				throw new BeanDefinitionStoreException(
						"Failed to process import candidates for configuration class [" +
						configClass.getMetadata().getClassName() + "]", ex);
			}
			finally {
				this.importStack.pop();
			}
		}
	}

spring事务中selectImport方法,返回AutoProxyRegistrar(对应于下面ImportBeanDefinitionRegistrar的处理逻辑)和ProxyTransactionManagementConfiguration(对应于下面configuration类的处理逻辑)两个组件类,在parser中,首先实例化selector,然后对selector.selectImports方法返回的对象,利用递归的调用,再处理registrar和configuration的配置类,向spring中注册对象。

6.3.3 ImportBeanDefinitionRegistrar

image-20220525172734173

这里的作用,跟ImportSelector功能相似,但是更强大。

public interface ImportBeanDefinitionRegistrar {
  
	/**importingClassMetadata 是@import所注解的类的元数据
  	BeanDefinitionRegistry 是spring的注册器*/
	default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
			BeanNameGenerator importBeanNameGenerator) {
		//内部调用
		registerBeanDefinitions(importingClassMetadata, registry);
	}

  //通过registry向容器中注册beandefinition对象
	default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
	}

}

6.3.3.1 AutoProxyRegistrar---spring事务注册类

public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	private final Log logger = LogFactory.getLog(getClass());

	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		boolean candidateFound = false;
    //
		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;
        //默认的proxy模式
				if (mode == AdviceMode.PROXY) {
          //注册autoProxyCreator类
					AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
					if ((Boolean) proxyTargetClass) {
						AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
						return;
					}
				}
			}
		}
	}

}
AopConfigUtils{
	@Nullable
	public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		return registerAutoProxyCreatorIfNecessary(registry, null);
	}

	@Nullable
	public static BeanDefinition registerAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
		//向spring注册InfrastructureAdvisorAutoProxyCreator类
		return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
	}

AutoProxyRegistrar类向spring注册事务的自动代理创建类InfrastructureAdvisorAutoProxyCreator。

6.3.4 InfrastructureAdvisorAutoProxyCreator

image-20230310134633256

image-20230310134649348

InfrastructureAdvisorAutoProxyCreator类同AOP中核心组件相同,实现后置处理器类,会在spring对象实例化、初始化前后,自动创建当前类的代理类。详见AOP中autoproxycreator类。

public class InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {

	@Nullable
	private ConfigurableListableBeanFactory beanFactory;


	@Override
	protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		super.initBeanFactory(beanFactory);
		this.beanFactory = beanFactory;
	}

  //判断是否是符合条件的AdvisorBean
	@Override
	protected boolean isEligibleAdvisorBean(String beanName) {
    //bean的role为BeanDefinition.ROLE_INFRASTRUCTURE
		return (this.beanFactory != null && this.beanFactory.containsBeanDefinition(beanName) &&
				this.beanFactory.getBeanDefinition(beanName).getRole() == BeanDefinition.ROLE_INFRASTRUCTURE);
	}

}

InfrastructureAdvisorAutoProxyCreator提供isEligibleAdvisorBean(String beanName)方法判断当前beanname是否是符合条件的AdvisorBean,而只有ProxyTransactionManagementConfiguration配置类创建的advisor、advice和AnnotationTransactionAttributeSource为BeanDefinition.ROLE_INFRASTRUCTURE。

因此该逻辑主要是筛查出这三个实例。

6.3.5 ProxyTransactionManagementConfiguration

该类是spring事务的重要配置类,用来自动创建事务所需要的advisor等重要组件类。

//配置类
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

/**…………………………………………………………………………………………………创建spring事务的advisor类……………………………………………………………………………………*/
	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
			TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
		//创建advisor类
		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
    //设置属性源source
		advisor.setTransactionAttributeSource(transactionAttributeSource);
    //设置advice增强
		advisor.setAdvice(transactionInterceptor);
		if (this.enableTx != null) {
      //如果有顺序属性,设置优先级
			advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
		}
		return advisor;
	}

/**…………………………………………………………创建spring事务的AnnotationTransactionAttributeSource类…………………………………………………*/
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
    ///该类用来解析@Transactional注解上的事务属性
		return new AnnotationTransactionAttributeSource();
	}

/**…………………………………………………………………………………………………创建spring事务的advice类……………………………………………………………………………………*/
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
		TransactionInterceptor interceptor = new TransactionInterceptor();
    //设置事务属性源
		interceptor.setTransactionAttributeSource(transactionAttributeSource);
		if (this.txManager != null) {
      //设置事务管理器
			interceptor.setTransactionManager(this.txManager);
		}
		return interceptor;
	}

}

配置类,创建spring事务所需要的advisor、advice和AnnotationTransactionAttributeSource(用来解析@Transactional上的事务属性)。

注意:

这个配置类内创建的三个实例,bean的role为BeanDefinition.ROLE_INFRASTRUCTURE。

6.3.6 @EnableXXX原理

@enableXXX注解,通过@Import(),作为开关功能的注解,开启XXX功能,可以通过ImportSelector、ImportBeanDefinitionRegistrar、Configuration类,向spring容器中动态添加注册相关的重要组件类,实现自动开关功能。

posted @ 2023-03-10 17:17  LeasonXue  阅读(82)  评论(0)    收藏  举报