1. Analyse du code source des fonctions principales de la transaction et de l'aop de Springboot

1. La différence et le lien entre AOP et transaction

La classe d'assemblage automatique qui introduit AOP est AopAutoConfiguration, et la classe d'assemblage automatique qui introduit les transactions est TransactionAutoConfiguration.

La fonctionnalité AOP est spring-boot-starter-aopfournie par les dépendances. La fonctionnalité de transaction est spring-txfournie par les dépendances.
insérez la description de l'image ici
Les proxy beans impliqués dans Aop & transaction incluent :

  1. Le bean proxy impliqué dans Aop implique principalement la classe spécifiée par pointcut.
  2. Les beans proxy impliqués dans la transaction impliquent principalement la classe avec @transaction et la classe avec la méthode avec cette annotation.

1.1、AopAutoConfiguration

Les types EnableAspectJAutoProxysont introduits par des annotations . Le but d'AspectJAutoProxyRegistrar est d'introduire les post-processeurs liés à AOP .ImportBeanDefinitionRegistrarAspectJAutoProxyRegistrarAnnotationAwareAspectJAutoProxyCreator

1.2、TransactionAutoConfiguration

Les types EnableTransactionManagementsont introduits par des annotations . Le but de TransactionManagementConfigurationSelector est d'introduire l'un des post-processeurs liés aux transactions , parmi lesquels le but d'AutoProxyRegistrar est d'introduire , et ProxyTransactionManagementConfiguration est d'introduire le point de connexion && lié aux transactions TransactionAttributeSourcePointcut.ImportSelectorTransactionManagementConfigurationSelectorAutoProxyRegistrarProxyTransactionManagementConfigurationInfrastructureAdvisorAutoProxyCreator环绕通知TransactionInterceptor切面BeanFactoryTransactionAttributeSourceAdvisor

Le bean dans l'aspect lié aux transactions BeanFactoryTransactionAttributeSourceAdvisor dans son conteneur IOC est org.springframework.transaction.config.internalTransactionAdvisor.

1.3、AopConfigUtils

La méthode principale de la classe consiste à initialiser la sous-classe de la classe abstraite AbstractAutoProxyCreator. Ses sous-classes sont toutes importées indirectement via la classe d'assemblage automatique. Et ces post-processeurs sont déclenchés lorsque les BeanDefinitions correspondantes sont complétées après le chargement de toutes les classes d'assemblage automatiques .

public abstract class AopConfigUtils {
    
    
	public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
			"org.springframework.aop.config.internalAutoProxyCreator";	
	static {
    
    
		APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
		APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
		APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
	}
	@Nullable
	public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    
    
		return registerAutoProxyCreatorIfNecessary(registry, null);
	}

	@Nullable
	public static BeanDefinition registerAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
    
    
		return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
	}

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

	@Nullable
	public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
    
    
		return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
	}

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

	@Nullable
	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
    
    

		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
	}

	@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;
	}
}

Si aop & transactions existent dans le projet en même temps, AspectJAutoProxyRegistrar et AutoProxyRegistrar initialisent respectivement les post-processeurs correspondants via AopConfigUtils. Cependant, étant donné que le beanName des deux post-processeurs dans le conteneur IOC est le même AUTO_PROXY_CREATOR_BEAN_NAME, registerOrEscalateApcAsRequiredon sait grâce à la méthode ci-dessus que seuls les post-processeurs liés à AOP existent dans ce cas.

2、AbstractAutoProxyCreator

public abstract class AbstractAutoProxyCreator implements SmartInstantiationAwareBeanPostProcessor{
    
    
	private BeanFactory beanFactory;
	private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);

	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    
    
		Object cacheKey = getCacheKey(beanClass, beanName);
		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
    
    
			if (this.advisedBeans.containsKey(cacheKey)) {
    
    
				return null;
			}
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
    
    
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		...
		return null;
	}
	...
	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    
    
		if (bean != null) {
    
    
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
    
    
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    
    
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
    
    
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
    
    
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
    
    
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}
		...
		// Create proxy if we have advice.
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);//#1
		if (specificInterceptors != DO_NOT_PROXY) {
    
    
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}
	protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
    
    
		// Handle prototypes correctly...
		Advisor[] commonInterceptors = resolveInterceptorNames();
		List<Object> allInterceptors = new ArrayList<>();
		if (specificInterceptors != null) {
    
    
			allInterceptors.addAll(Arrays.asList(specificInterceptors));
			if (commonInterceptors.length > 0) {
    
    
				if (this.applyCommonInterceptorsFirst) {
    
    
					allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
				}
				else {
    
    
					allInterceptors.addAll(Arrays.asList(commonInterceptors));
				}
			}
		}
		Advisor[] advisors = new Advisor[allInterceptors.size()];
		for (int i = 0; i < allInterceptors.size(); i++) {
    
    
			advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
		}
		return advisors;
	}
}

La propriété advisorBeans du type de collection Map, son élément est un bean proxy inutile.
isInfrastructureClass : indique s'il s'agit d'une classe d'infrastructure liée à aop. infrastructureClass inclut Advice, Pointcut, Advisor, AopInfrastructureBean et @Aspect fournis par AnnotationAwareAspectJAutoProxyCreator. Aucune de ces classes d'infrastructure ne nécessite de traitement proxy.

  • Etape 1 : AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean, pour obtenir différents conseils de la classe d'aspect Advisor correspondant au bean courant et le type Interceptor correspondant dans la classe d'aspect.

2.1、AbstractAdvisorAutoProxyCreator

public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
    
    
	private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;
	
	protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,TargetSource targetSource) {
    
    
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
    
    
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}
	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    
    
		List<Advisor> candidateAdvisors = findCandidateAdvisors();//#1
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);//#2
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
    
    
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}
	protected List<Advisor> findCandidateAdvisors() {
    
    //#3
		return this.advisorRetrievalHelper.findAdvisorBeans();
	}

	protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
    
    
		ProxyCreationContext.setCurrentProxiedBeanName(beanName);
		try {
    
    
			return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
		}
		finally {
    
    
			ProxyCreationContext.setCurrentProxiedBeanName(null);
		}
	}

	private class BeanFactoryAdvisorRetrievalHelperAdapter extends BeanFactoryAdvisorRetrievalHelper {
    
    
		public BeanFactoryAdvisorRetrievalHelperAdapter(ConfigurableListableBeanFactory beanFactory) {
    
    
			super(beanFactory);
		}
		@Override
		protected boolean isEligibleBean(String beanName) {
    
    
			return AbstractAdvisorAutoProxyCreator.this.isEligibleAdvisorBean(beanName);
		}
	}
}
  1. Étape 1 : Obtenir les classes d'aspects des candidats
  • S'il y a une transaction, elle obtient principalement org.springframework.transaction.config.internalTransactionAdvisorla classe d'aspect candidat Advisor dont le beanName est BeanFactoryTransactionAttributeSourceAdvisor. Le candidat Advisor n'est pas obtenu à l'aide d'InfrastructureAdvisorAutoProxyCreator.
  • S'il y a aop, il est fourni par sa sous-classe AnnotationAwareAspectJAutoProxyCreator, comme suit :
protected List<Advisor> findCandidateAdvisors() {
    
    List<Advisor> advisors = super.findCandidateAdvisors();//AbstractAdvisorAutoProxyCreator#findCandidateAdvisors
	// Build Advisors for all AspectJ aspects in the bean factory.
	if (this.aspectJAdvisorsBuilder != null) {
    
    
		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
	}
	return advisors;
}

Comme indiqué ci-dessus, AnnotationAwareAspectJAutoProxyCreator essaie d'obtenir le conseiller de la classe d'aspect sélectionnée et le conseiller du type AspectJ. Si transaction & Aop existent dans l'application en même temps, les conseillers correspondant aux deux sont fournis par AnnotationAwareAspectJAutoProxyCreator [Parce que le post-processeur de InfrastructureAdvisorAutoProxyCreator et AnnotationAwareAspectJAutoProxyCreator ont le même beanName , seul ce dernier existe dans le conteneur IOC] org.springframework.aop.config.internalAutoProxyCreator.

  1. Étape 2 : Dans le processus d'initialisation du bean dans l'application, tous les conseillers de classe d'aspect [transaction et Aop] sont d'abord initialisés, puis à travers cette étape, les conseillers candidats dont le bean actuel a réellement besoin sont déterminés. Si le bean actuel n'a que des transactions, filtrez la classe d'aspect liée à l'AOP Advisor...etc.
  2. BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans, la logique de base obtient principalement la classe d'aspect candidate Advisor, telle que BeanFactoryTransactionAttributeSourceAdvisor, par exemple comme suit :
public class BeanFactoryAdvisorRetrievalHelper {
    
    

	public List<Advisor> findAdvisorBeans() {
    
    
		String[] advisorNames = this.cachedAdvisorBeanNames;
		if (advisorNames == null) {
    
    
			// 从IOC容器DefaultListableBeanFactory中获取Advisor相关的beanName
			//例如事务相关的org.springframework.transaction.config.internalTransactionAdvisor
			advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
					this.beanFactory, Advisor.class, true, false);
			this.cachedAdvisorBeanNames = advisorNames;
		}
		if (advisorNames.length == 0) {
    
    
			return new ArrayList<>();
		}
		List<Advisor> advisors = new ArrayList<>();
		for (String name : advisorNames) {
    
    
			if (isEligibleBean(name)) {
    
    
				if (this.beanFactory.isCurrentlyInCreation(name)) {
    
    
				}else {
    
    
					advisors.add(this.beanFactory.getBean(name, Advisor.class));
				}
			}
		}
		return advisors;
	}

}

isEligibleBean : renvoie vrai par défaut. Le post-processeur InfrastructureAdvisorAutoProxyCreator remplace cette méthode.

Je suppose que tu aimes

Origine blog.csdn.net/qq_36851469/article/details/129971445
conseillé
Classement