1. Análisis del código fuente de las funciones principales de la transacción y aop de Springboot

1. La diferencia y conexión entre AOP y transacción

La clase de ensamblaje automático que presenta AOP es AopAutoConfiguration, y la clase de ensamblaje automático que presenta transacciones es TransactionAutoConfiguration.

Las dependencias proporcionan la funcionalidad AOP spring-boot-starter-aop. La funcionalidad de transacciones la spring-txproporcionan las dependencias.
inserte la descripción de la imagen aquí
Los frijoles proxy involucrados en Aop y transacciones incluyen:

  1. El bean proxy involucrado en Aop involucra principalmente la clase especificada por pointcut.
  2. Los beans proxy involucrados en la transacción involucran principalmente la clase con @transaction y la clase con el método con esta anotación.

1.1, Configuración automática de Aop

Los tipos EnableAspectJAutoProxyse introducen mediante anotaciones . El propósito de AspectJAutoProxyRegistrar es introducir postprocesadores relacionados con AOP .ImportBeanDefinitionRegistrarAspectJAutoProxyRegistrarAnnotationAwareAspectJAutoProxyCreator

1.2, Configuración automática de transacciones

Los tipos EnableTransactionManagementse introducen mediante anotaciones . El propósito de TransactionManagementConfigurationSelector es introducir uno de los posprocesadores relacionados con transacciones , entre los cuales el propósito de AutoProxyRegistrar es introducir , y ProxyTransactionManagementConfiguration es introducir el punto de conexión && relacionado con transacciones TransactionAttributeSourcePointcut.ImportSelectorTransactionManagementConfigurationSelectorAutoProxyRegistrarProxyTransactionManagementConfigurationInfrastructureAdvisorAutoProxyCreator环绕通知TransactionInterceptor切面BeanFactoryTransactionAttributeSourceAdvisor

El bean en el aspecto relacionado con la transacción BeanFactoryTransactionAttributeSourceAdvisor en su contenedor IOC es org.springframework.transaction.config.internalTransactionAdvisor.

1.3, AopConfigUtils

El método principal de la clase es inicializar la subclase de la clase abstracta AbstractAutoProxyCreator. Todas sus subclases se importan indirectamente a través de la clase de ensamblaje automático. Y estos posprocesadores se activan cuando las BeanDefinitions correspondientes se completan después de que se cargan todas las clases de ensamblado automático .

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 y transacciones existen en el proyecto al mismo tiempo, AspectJAutoProxyRegistrar y AutoProxyRegistrar inicializan los posprocesadores correspondientes a través de AopConfigUtils respectivamente. Sin embargo, dado que el beanName de los dos posprocesadores en el contenedor IOC es el mismo AUTO_PROXY_CREATOR_BEAN_NAME, registerOrEscalateApcAsRequiredse sabe a través del método anterior que solo existen posprocesadores relacionados con AOP en este caso.

2, Creador de proxy automático abstracto

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 propiedad advisorBeans del tipo de colección Map, su elemento es un bean proxy innecesario.
isInfrastructureClass: indica si se trata de una clase de infraestructura relacionada con aop. InfrastructureClass incluye Advice, Pointcut, Advisor, AopInfrastructureBean y @Aspect proporcionados por AnnotationAwareAspectJAutoProxyCreator. Ninguna de estas clases de infraestructura requiere procesamiento de proxy.

  • Paso 1: AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean, para obtener varios avisos del Asesor de clase de aspecto correspondiente al bean actual y el tipo de Interceptor correspondiente en la clase de aspecto.

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. Paso 1: Obtener clases de aspecto candidatas
  • Si hay una transacción, obtiene principalmente org.springframework.transaction.config.internalTransactionAdvisorel Advisor de clase de aspecto candidato cuyo beanName es BeanFactoryTransactionAttributeSourceAdvisor. El Asesor candidato no se obtiene con la ayuda de InfrastructureAdvisorAutoProxyCreator.
  • Si hay aop, lo proporciona su subclase AnnotationAwareAspectJAutoProxyCreator, de la siguiente manera:
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;
}

Como se muestra arriba, AnnotationAwareAspectJAutoProxyCreator intenta obtener el Asesor de la clase de aspecto seleccionada y el Asesor del tipo AspectJ. Si la transacción y Aop existen en la aplicación al mismo tiempo, AnnotationAwareAspectJAutoProxyCreator proporciona los asesores correspondientes a los dos [debido a que el posprocesador de InfrastructureAdvisorAutoProxyCreator y AnnotationAwareAspectJAutoProxyCreator tienen el mismo beanName, solo el último existe en el contenedor IOC] org.springframework.aop.config.internalAutoProxyCreator.

  1. Paso 2: en el proceso de inicialización del bean en la aplicación, primero se inicializan todos los asesores de clase de aspecto [transacción y Aop] y luego, a través de este paso, se determinan los asesores candidatos que realmente necesita el bean actual. Si el bean actual solo tiene transacciones, filtre el asesor de clase de aspecto relacionado con AOP... etc.
  2. BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans, la lógica central obtiene principalmente el Asesor de clase de aspecto candidato, como BeanFactoryTransactionAttributeSourceAdvisor, por ejemplo, de la siguiente manera:
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: devuelve verdadero por defecto. El posprocesador de InfrastructureAdvisorAutoProxyCreator anula este método.

Supongo que te gusta

Origin blog.csdn.net/qq_36851469/article/details/129971445
Recomendado
Clasificación