Administrator
发布于 2025-01-13 / 7 阅读
0
0

Spring创建Bean & AOP & Transaction

Spring创建Bean & AOP & Transaction

Spring创建Bean

Spring来生成bean,就是让注解生效,自动注入属性值 和 生成代理类。

refer to : https://segmentfault.com/a/1190000045553851

image-20250113145241135

将AOP应用到Bean的生命周期

refer to : https://blog.csdn.net/qq_41907991/article/details/107141101

image-20250113145241135

本文我们要分析的代码还是位于 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean这个方法中,在《 我们来谈一谈Spring中的属性注入 》这篇文章中,我们已经分析过了 populateBean这个方法,

image-20250113150201478

所以本文我们接着来看看initializeBean这个方法,它主要干了这么几件事

  1. 执行Aware接口中的方法
  2. 执行生命周期回调方法
  3. 完成AOP代理
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
           
            // 执行Aware接口中的方法
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
            
            // 调用InitDestroyAnnotationBeanPostProcessor
            // 的postProcessBeforeInitialization方法
            // 处理@PostContructor注解标注的方法
            // 另外有一部分aware方法也是在这里调用的
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
            // 如果实现了InitializingBean,会调用afterPropertiesSet方法
            // 如果XML中配置了init-method属性,会调用对应的初始化方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
            // 在这里完成AOP
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

我们主要关注的就是Spring是如何将AOP应用到Bean的生命周期中的,对应的就是applyBeanPostProcessorsAfterInitialization这个方法,其源码如下:

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

实际上就是调用了所有后置处理器的postProcessAfterInitialization方法,在Spring中AOP相关的API及源码解析,原来AOP是这样子的一文中已经提到过了,@EnableAspectJAutoProxy注解实际上就是向容器中注册了一个AnnotationAwareAspectJAutoProxyCreator,这个类本身就是一个后置处理器,AOP代理就是由它在这一步完成的。

Bean生命周期中AOP的流程

1、@EnableAspectJAutoProxy

通过@EnableAspectJAutoProxy注解向容器中注册一个AnnotationAwareAspectJAutoProxyCreator的BeanDefinition,它本身也是一个BeanPostProcessor,这个BeanDefinition会在org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors这个方法中完成创建,如下图所示

image-20250113150412790

2、postProcessBeforeInstantiation方法执行

执行AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation方法,实际上就是父类AbstractAutoProxyCreator的postProcessBeforeInstantiation被执行

对应源码如下:

//  这个方法的主要目的就是在不考虑通知的情况下,确认哪些Bean不需要被代理
//  1.Advice,Advisor,Pointcut类型的Bean不需要被代理
//  2.不是原始Bean被包装过的Bean不需要被代理,例如ScopedProxyFactoryBean
//  实际上并不只是这些Bean不需要被代理,如果没有对应的通知需要被应用到这个Bean上的话
//  这个Bean也是不需要被代理的,只不过不是在这个方法中处理的。
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    Object cacheKey = getCacheKey(beanClass, beanName);
    // 如果beanName为空或者为这个bean提供了定制的targetSource
    if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
        // advisedBeans是一个map,其中key是BeanName,value代表了这个Bean是否需要被代理
        // 如果已经包含了这个key,不需要在进行判断了,直接返回即可
        // 因为这个方法的目的就是在实例化前就确认哪些Bean是不需要进行AOP的
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }
        // 说明还没有对这个Bean进行处理
        // 在这里会对SpringAOP中的基础设施bean,例如Advice,Pointcut,Advisor做标记
        // 标志它们不需要被代理,对应的就是将其放入到advisedBeans中,value设置为false
        // 其次,如果这个Bean不是最原始的Bean,那么也不进行代理,也将其value设置为false
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }

    // 是否为这个Bean提供了定制的TargetSource
    // 如果提供了定制的TargetSource,那么直接在这一步创建一个代理对象并返回
    // 一般不会提供
    TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
    if (targetSource != null) {
        if (StringUtils.hasLength(beanName)) {
            this.targetSourcedBeans.add(beanName);
        }
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
        Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    return null;
}

3、postProcessAfterInitialization方法执行

实际上也是执行父类AbstractAutoProxyCreator中的方法,对应源码如下:

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        // 什么时候这个判断会成立呢?
        // 如果不出现循环引用的话,remove方法必定返回null
        // 所以这个remove(cacheKey) != bean肯定会成立
        // 如果发生循环依赖的话,这个判断就不会成立
        // 这个我们在介绍循环依赖的时候再详细分析,
       	// 目前你只需要知道wrapIfNecessary完成了AOP代理
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            // 需要代理的话,在这里完成的代理
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

4、wrapIfNecessary方法执行

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
   
    // 在postProcessBeforeInstantiation方法中可能已经完成过代理了
    // 如果已经完成代理了,那么直接返回这个代理的对象
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    
    // 在postProcessBeforeInstantiation方法中可能已经将其标记为不需要代理了
    // 这种情况下,也直接返回这个Bean
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    
    // 跟在postProcessBeforeInstantiation方法中的逻辑一样
    // 如果不需要代理,直接返回,同时在advisedBeans中标记成false
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // 获取可以应用到这个Bean上的通知
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    // 如果存在通知的话,说明需要被代理
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 到这里创建代理,实际上底层就是new了一个ProxyFactory来创建代理的
        Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }
	// 如果没有通知的话,也将这个Bean标记为不需要代理
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

关于创建代理的具体源码分析,在Spring中AOP相关的API及源码解析,原来AOP是这样子的一文中已经做了详细介绍,所以本文不再赘述,现在我们的重点将放在Spring是如何解析出来通知的,对应方法就是getAdvicesAndAdvisorsForBean,其源码如下:

第一步:调用org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean

protected Object[] getAdvicesAndAdvisorsForBean(
      Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
  
   // 通过findEligibleAdvisors方法返回对应的通知
   // 这个方法回返回所有能应用在指定的Bean上的通知
   List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
   
   if (advisors.isEmpty()) {
      return DO_NOT_PROXY;
   }
   return advisors.toArray();
}

第二步:调用org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 获取到所有的通知
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 从获取到的通知中筛选出能应用到这个Bean上的通知
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

第三步:调用org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors获取到所有的通知

// 这个方法的目的就是为了获取到所有的通知
protected List<Advisor> findCandidateAdvisors() {
   
    // 先调用父类的方法,父类会去查找容器中所有属于Advisor类型的Bean
    List<Advisor> advisors = super.findCandidateAdvisors();
    
  	// 这个类本身会通过一个aspectJAdvisorsBuilder来构建通知
    // 构建的逻辑就是解析@Aspect注解所标注的类中的方法
    if (this.aspectJAdvisorsBuilder != null) {
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    
    // 最后返回这些通知
    return advisors;
}

第四步:org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors构建通知,这个方法比较长,我们就只分析其中的关键代码即可

public List<Advisor> buildAspectJAdvisors() {
		List<String> aspectNames = this.aspectBeanNames;

		if (aspectNames == null) {
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new ArrayList<>();
					aspectNames = new ArrayList<>();
					// 会获取到容器中的所有BeanName
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
					for (String beanName : beanNames) {
						// 如果对beanName配置了正则匹配的话,那么要按照正则表达式的匹配规则进行过滤
						// 默认是没有的,可以认为isEligibleBean始终返回true
						if (!isEligibleBean(beanName)) {
							continue;
						}
						// We must be careful not to instantiate beans eagerly as in this case they
						// would be cached by the Spring container but would not have been weaved.
						Class<?> beanType = this.beanFactory.getType(beanName);
						if (beanType == null) {
							continue;
						}
						// 判断类上是否添加了@Aspect注解
						if (this.advisorFactory.isAspect(beanType)) {
							aspectNames.add(beanName);
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							// 默认就是SINGLETON,代理切面对象是单例的
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                            // 最后从这个切面实例中解析出所有的通知
                            // 关于通知解析的具体代码就不再分析了
 								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
								if (this.beanFactory.isSingleton(beanName)) {
									this.advisorsCache.put(beanName, classAdvisors);
								}
								else {
									this.aspectFactoryCache.put(beanName, factory);
								}
								advisors.addAll(classAdvisors);
							}
		// 省略部分代码
		return advisors;
	}

第五步:org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply

protected List<Advisor> findAdvisorsThatCanApply(
    List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

    ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    try {
        return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    }
    finally {
        ProxyCreationContext.setCurrentProxiedBeanName(null);
    }
}

这个方法其实没啥好分析的,就是根据前面找出来的Advisor集合进行遍历,然后根据每个Advisor对应的切点来进行匹配,如何合适就返回,对应源码也比较简单,当然前提是你看过我之前那篇AOP源码分析的文章了.

总结

这篇文章比较短,因为没有做很细节的源码分析,比较详细的源码分析已经放到上篇文章中了。最后我这里画个流程图总结一下AOP是怎么被应用到Bean的生命周期中的

image-20250113151013875

将事物,应用到AOP中

refer to : https://blog.csdn.net/wang489687009/article/details/121214357

前言

通过前面对源码的分析,我们基本了解了整个 AOP 代理生产的过程:

找到与 bean 匹配的所有的 Advisor
使用所有匹配的 Advisor 来为 bean 生成生成动态代理
通过动态代理类执行 Advice
将 Spring AOP 与 Spring IoC 进行结合
我们知道 Spring 的事务管理也是通过 AOP 来实现的。接下来,我们就通过前面所积累的知识来分析一下: Spring 中的 @Transactional 是如何工作的?

版本约定:

Spring 5.3.9 (通过 SpringBoot 2.5.3 间接引入的依赖)

正文

前面分析 如何为 Pointcut 匹配的类生成动态代理类 时,我们发现,Spring 是在 bean 创建时的第三步 initializeBean 时,调用 AnnotationAwareAspectJAutoProxyCreator#postProcessAfterInitialization() 来产生代理 bean 的。

说的更具体点,是在调用父类的 AbstractAutoProxyCreator#wrapIfNecessary() 方法时,获取到与 bean 匹配的 Advisor,通过 ProxyFactory 来创建的代理类。

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

// AbstractAutoProxyCreator#wrapIfNecessary()
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    ......

    // Create proxy if we have advice.
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 创建代理 bean  
        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;
}

接下来,我们就通过 AnnotationAwareAspectJAutoProxyCreator 这条线索,来分析一下含有 @Transactional 的类是如何产生 AOP 代理类的?

通过源码处的条件断点来研究

我们直接在 AbstractAutoProxyCreator#wrapIfNecessary() 方法中创建代理处打一个断点。
可以发现,匹配到的 Advisor 是: BeanFactoryTransactionAttributeSourceAdvisor

我们再看一下 BeanFactoryTransactionAttributeSourceAdvisor 被引用的地方,可以发现是在 ProxyTransactionManagementConfiguration 中。
而 ProxyTransactionManagementConfiguration 被引用的地方则是 @EnableTransactionManagement

ProxyTransactionManagementConfiguration 具体的配置类如下:

@Configuration(proxyBeanMethods = false)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

    @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
            TransactionAttributeSource transactionAttributeSource,
            TransactionInterceptor transactionInterceptor) {
        // 使用的 pointcut 是: TransactionAttributeSourcePointcut  
        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        // TransactionAttributeSource 是用来获取事务元数据的
        advisor.setTransactionAttributeSource(transactionAttributeSource);
        // 针对 @Transactional 使用的 Advice 
        advisor.setAdvice(transactionInterceptor);
        if (this.enableTx != null) {
            advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
        }
        return advisor;
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource();
    }

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

}

通过 ProxyTransactionManagementConfiguration 的配置,我们可以看出,它定义了 advisor : BeanFactoryTransactionAttributeSourceAdvisor

BeanFactoryTransactionAttributeSourceAdvisor

Advisor 是 Spring AOP 产生代理类的关键配置,它包含了 pointcut 和 advice。(通常是 PointcutAdvisor)
pointcut 用于匹配 bean,对应的 advice 用于通知。

BeanFactoryTransactionAttributeSourceAdvisor 中包含的 pointcut 和 advice:

pointcut :
TransactionAttributeSourcePointcut 用于匹配 @Transactional 标记的方法对应的类(或者直接被 @Transactional 标记的类)
advice:
TransactionInterceptor 用于处理事务方法的执行拦截

TransactionInterceptor

事务的开启和提交,都是通过 TransactionInterceptor#invoke() 来进行拦截处理的。

// TransactionInterceptor#invoke()
public Object invoke(MethodInvocation invocation) throws Throwable {
    // Work out the target class: may be {@code null}.
    // The TransactionAttributeSource should be passed the target class
    // as well as the method, which may be from an interface.
    Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

    // Adapt to TransactionAspectSupport's invokeWithinTransaction...
    return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}

image-20250113154545484

可以看出,invokeWithinTransaction() 是带事务执行目标方法,如果目标方法正常返回的话,就会提交事务;如果目标方法抛出异常,则会判断该异常是否需要回滚事务。

invokeWithinTransaction() 的处理流程如下:

1.获取待执行方法上的事务属性 TransactionAttribute
即:方法上的 @Transactional 注解中的配置属性
2.选取事务管理器 TransactionManager
3.通过TransactionManager开启事务
4.执行目标方法
5.正常返回,则通过TransactionManager提交事务
6.异常返回,则判断是否需要回滚事务

小结

Spring 使用 Spring AOP 框架来为 @Transactional 标记的类或方法产生 AOP 代理类的方式来处理事务方法。
具体是定义了一个 Advisor : BeanFactoryTransactionAttributeSourceAdvisor,来拦截 @Transactional 方法。

BeanFactoryTransactionAttributeSourceAdvisor 中包含的 pointcut 和 advice:

pointcut :
TransactionAttributeSourcePointcut 用于匹配 @Transactional 标记的方法对应的类(或者直接被 @Transactional 标记的类)
advice:
TransactionInterceptor 用于处理事务方法的执行拦截
TransactionInterceptor#invoke() 会调用父类的 invokeWithinTransaction() 方法来完成事务方法的执行。
invokeWithinTransaction() 的处理流程如下:

获取待执行方法上的事务属性 TransactionAttribute
即:方法上的 @Transactional 注解中的配置属性
选取事务管理器 TransactionManager
通过TransactionManager开启事务
执行目标方法
正常返回,则通过TransactionManager提交事务
异常返回,则判断是否需要回滚事务(默认对 RuntimeException 和 Error 进行回滚)


评论