Spring源码之事务(一)

声明式事务简单示例
service 实现类
@Service
public class ProductInfoServiceImpl implements ProductInfoService {

    @Autowired
    private ProductInfoMapper productInfoMapper;

    @Transactional
    @Override
    public void addRequired(ProductInfo productInfo) {
        productInfoMapper.insert(productInfo);
        throw new RuntimeException("发生异常......");
    }
}
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 配置 springIOC 容器要管理的Bean(包扫描) -->
    <context:component-scan base-package="com.atguigu">
        <!-- 排除 @Controller 的注解的包,不需要扫描 -->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!-- 数据源配置 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url"
                  value="jdbc:mysql://127.0.0.1:3306/db_test?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai&amp;verifyServerCertificate=false&amp;useSSL=false"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
        <!-- 初始化时获取的连接数,默认是 0 -->
        <property name="initialSize" value="3"/>
        <!-- 连接池中保留的最小线程空闲数,默认为 0 -->
        <property name="minIdle" value="3"/>
        <!-- 连接池中保留的最大线程空闲数,默认为 8 -->
        <property name="maxIdle" value="8"/>
        <!-- 连接池中最大的连接数,默认值: 8 -->
        <property name="maxActive" value="8"/>
        <!-- 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
        <property name="maxWait" value="60000"/>
    </bean>

    <!-- spring 和 mybatis 整合 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 指定 mybatis 要连接的数据源 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- mybatis 配置文件的地址 -->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!-- mybatis 的 mapper 文件的地址 -->
        <property name="mapperLocations" value="classpath:com/atguigu/mapper/*.xml"/>
    </bean>

    <!-- 配置 Mapper 接口扫描 -->
    <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.atguigu.mapper"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>

    <!-- 配置Spring的事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 开启注解式事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
测试类
public class TransactionTest_1 {

    @Test
    public void notransaction_exception_required_required() {
        /* 初始化启动 spring ioc 容器 */
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-spring.xml");
        /* 从 spring ioc 容器中获取一个 bean */
        ProductInfoService productInfoService = (ProductInfoService) applicationContext.getBean("productInfoServiceImpl");

        BigDecimal bigDecimal = new BigDecimal("1499.00");
        ProductInfo productInfo = new ProductInfo(12, "HUAWEI nova 5z", bigDecimal, 100, "极致体验", 1);
        productInfoService.addRequired(productInfo);// 此方法开启了事务
    }
}
测试结果1

88363ED4-7C9F-3BC3-EFA1-1AD5905E4EBA.png

测试结果2

去除

throw new RuntimeException("发生异常......");

时,结果如下

E3E21F0B-F702-0A2C-EF7A-BA5F8869A3DC.png

spring 事务源码解读

我们首先从配置文件开始入手,在配置文件中配置了 <tx:annotation-driven />。这个配置是事务的开关,如果没有此处配置,那么 spring 光靠 @Transactional 注解不能开启事务的功能。那么我们就从这个配置开始分析

spring 事务配置文件的解析

使用开发工具进入 DEBUG 模式,给下面的代码打上断点:

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-spring.xml");
进入类 ClassPathXmlApplicationContext 的构造器
public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {

		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
}

看一下它的核心方法肯定就在 refresh() 里面,实际上它调用的是抽象类AbstractApplicationContextrefresh()

AbstractApplicationContextrefresh()方法(重点
@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
		
			/**
			 * 刷新上下文环境,初始化上下文环境,对系统的环境变量或者系统属性进行准备和校验
			 */
			prepareRefresh();

			// 该方法会解析所有 spring 配置文件(通常我们会放在 resources 目录下)
			// 将配置文件中的 bean 定义封装成 BeanDefinition,加载到 BeanFactory 中
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			/**
			 * 为上下文准备BeanFactory,即对BeanFactory的各种功能进行填充,如常用的注解@Autowired @Qualifier等
			 * 设置SPEL表达式#{key}的解析器
			 * 设置资源编辑注册器,如PerpertyEditorSupper的支持
			 * 添加ApplicationContextAwareProcessor处理器
			 * 在依赖注入忽略实现*Aware的接口,如EnvironmentAware、ApplicationEventPublisherAware等
			 * 注册依赖,如一个bean的属性中含有ApplicationEventPublisher(beanFactory),则会将beanFactory的实例注入进去
			 */
			prepareBeanFactory(beanFactory);

			try {
				/**
				 * 提供子类覆盖的额外处理,即子类处理自定义的BeanFactoryPostProcess
				 * 在当前上下文使用的Bean容器BeanFactory的标准初始化完成后对其做一些修改。此时
				 * 所有的Bean definition都已经加载但是还没有 Bean 被创建
				 */
				postProcessBeanFactory(beanFactory);

				/**
				 * 实例化和调用所有 BeanFactoryPostProcessor,包括其子类 BeanDefinitionRegistryPostProcessor
				 * 激活各种BeanFactory处理器,包括BeanDefinitionRegistryBeanFactoryPostProcessor和普通的BeanFactoryPostProcessor
				 * 执行对应的postProcessBeanDefinitionRegistry方法 和  postProcessBeanFactory方法
				 */
				invokeBeanFactoryPostProcessors(beanFactory);

				/**
				 * 注册所有的 BeanPostProcessor,将所有实现了 BeanPostProcessor 接口的类加载到 BeanFactory 中
				 * 注册拦截Bean创建的Bean处理器,即注册BeanPostProcessor,不是BeanFactoryPostProcessor,注意两者的区别
				 * 注意,这里仅仅是注册,并不会执行对应的方法,将在bean的实例化时执行对应的方法
				 */				
				registerBeanPostProcessors(beanFactory);

				// 初始化上下文中的资源文件,如国际化文件的处理等
				initMessageSource();

				// 初始化上下文事件广播器,并放入applicatioEventMulticaster,如ApplicationEventPublisher
				initApplicationEventMulticaster();

				// 给子类扩展初始化其他Bean
				onRefresh();

				// 注册监听器
				registerListeners();

				/**
				 * 设置转换器
				 * 注册一个默认的属性值解析器
				 * 冻结所有的bean定义,说明注册的bean定义将不能被修改或进一步的处理
				 * 初始化剩余的非惰性的bean,即初始化非延迟加载的bean
				 */
				finishBeanFactoryInitialization(beanFactory);

				/**
				 * 初始化生命周期处理器DefaultLifecycleProcessor,DefaultLifecycleProcessor含有start方法和stop方法,spring启动的时候调用start方法开始生命周期,
				 * spring关闭的时候调用stop方法来结束生命周期,通常用来配置后台程序,启动有一直运行,如一直轮询kafka
				 * 启动所有实现了Lifecycle接口的类
				 * 通过spring的事件发布机制发布ContextRefreshedEvent事件,以保证对应的监听器做进一步的处理,即对那种在spring启动后需要处理的一些类,这些类实现了
				 * ApplicationListener<ContextRefreshedEvent> ,这里就是要触发这些类的执行(执行onApplicationEvent方法)另外,spring的内置Event有ContextClosedEvent、ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent、RequestHandleEvent
				 * 完成初始化,通知生命周期处理器lifeCycleProcessor刷新过程,同时发出ContextRefreshEvent通知其他人
				 */
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}
				destroyBeans();
				cancelRefresh(ex);
				throw ex;
			}
			finally {
				resetCommonCaches();
			}
		}
	}
AbstractApplicationContextrefresh()中的重点方法:
  • obtainFreshBeanFactory():解析所有 spring 配置文件,将配置文件中的 bean 定义封装成 BeanDefinition,加载到 BeanFactory
  • invokeBeanFactoryPostProcessors :提供给开发者对 BeanFactory 进行扩展
  • registerBeanPostProcessors :提供给开发者对 bean 进行扩展
  • finishBeanFactoryInitialization :实例化剩余的所有非懒加载单例 bean
obtainFreshBeanFactory() 方法

该方法会解析所有 spring 配置文件(通常我们会放在 resources 目录下),将配置文件中的 bean 定义封装成 BeanDefinition,加载到 BeanFactory 中。鉴于篇幅,关于这个方法本篇不再赘述,Spring IoC源码学习:ObtainFreshBeanFactory 详解,最终会进入方法 parseBeanDefinitions

DefaultBeanDefinitionDocumentReaderparseBeanDefinitions 方法

解析每一个 <bean>...</bean>,或者自定义的标签,如<tx: ...>

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
	
	// 1.默认命名空间的处理 
	if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					// 判断是否是自定义的 bean 的声明
					if (delegate.isDefaultNamespace(ele)) {
						// 默认命名空间节点的处理,例如: <bean id="test" class="" />
						parseDefaultElement(ele, delegate);
					}
					else {
						// 自定义命名空间节点的处理,例如:<context:component-scan/>、<aop:aspectj-autoproxy/>
						delegate.parseCustomElement(ele);
					}
				}
			}
	}
	else {
		// 2.自定义命名空间的处理
		delegate.parseCustomElement(root);
	}		
}
DEBUG 模式进入 delegate.parseCustomElement(ele) 方法
@Nullable
public BeanDefinition parseCustomElement(Element ele) {
	// 调用如下
	return parseCustomElement(ele, null);
}


@Nullable
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
		String namespaceUri = getNamespaceURI(ele);
		if (namespaceUri == null) {
			return null;
		}
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
进入 resolve() 方法

DefaultNamespaceHandlerResolver 类中

@Override
@Nullable
public NamespaceHandler resolve(String namespaceUri) {
		
		// 获取所有已配置的 Handler 映射缓存
		Map<String, Object> handlerMappings = getHandlerMappings();
		// 从 handlerMappings 中获取 namespaceUri 对应的 NamespaceHandler 全类名
		Object handlerOrClassName = handlerMappings.get(namespaceUri);
		if (handlerOrClassName == null) {
			return null;
		}
		// 已做过解析的情况下,直接从缓存中获取
		else if (handlerOrClassName instanceof NamespaceHandler) {
			return (NamespaceHandler) handlerOrClassName;
		}
		else {
			// 如果没有做过解析,直接返回类路径,进行反射
			String className = (String) handlerOrClassName;
			try {
				Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
				if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
					throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
							"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
				}
				// 初始化类
				NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
				// 调用自定义的 namespaceHandler 的初始化方法
				namespaceHandler.init();
				// 记录在 handlerMappings 缓存中
				handlerMappings.put(namespaceUri, namespaceHandler);
				return namespaceHandler;
			}
			catch (ClassNotFoundException ex) {
				throw new FatalBeanException("Could not find NamespaceHandler class [" + className +
						"] for namespace [" + namespaceUri + "]", ex);
			}
			catch (LinkageError err) {
				throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
						className + "] for namespace [" + namespaceUri + "]", err);
			}
		}
}
进入 namespaceHandler.init() 方法
public class TxNamespaceHandler extends NamespaceHandlerSupport {

	static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";

	static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";


	static String getTransactionManagerName(Element element) {
		return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
				element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
	}


	@Override
	public void init() {
		registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
		registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
		registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
	}
}

我们可以看到 annotation-driven 的解析类是 AnnotationDrivenBeanDefinitionParser

进入 AnnotationDrivenBeanDefinitionParser 类中查看其 parse() 方法

事务的 annotation-driven 标签的的解析

@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
   registerTransactionalEventListenerFactory(parserContext);
   
   // 获取 mode 属性设置
   String mode = element.getAttribute("mode");
   if ("aspectj".equals(mode)) {
      // mode="aspectj"
      registerTransactionAspect(element, parserContext);
      if (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader())) {
         registerJtaTransactionAspect(element, parserContext);
      }
   }
   else {
      // mode="proxy"
      AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
   }
   return null;
}
tx:annotation-driven 一共有四个属性如下:
  • mode:指定 spring 事务管理框架创建通知 bean 的方式。可用的值有 proxyaspectj。前者是默认值,表示通知对象是个 JDK 代理;后者表示 spring aop 会使用 AspectJ 创建代理
  • proxy-target-class:如果为 truespring 将创建子类来代理业务类;如果为 false,则使用基于接口的代理。(如果使用子类代理,需要在类路径中添加 CGLib.jar 类库)
  • order:如果业务类除事务切面外,还需要织入其他的切面,通过该属性可以控制事务切面在目标连接点的织入顺序
  • transaction-manager:指定到现有的 PlatformTransactionManager bean 的引用,通知会使用该引用

parse() 方法主要获取自定义 annotation-driven 标签的 mode 属性值,属性值默认为 proxy,除此之外可以配置成 aspectj

  • proxy 是代理模式,仅在外部方法调用才会被代理截获,自身方法调用,即使配置了 @Transactional注解事务也无法生效,此外代理模式也不能应用在非 public 方法上
  • aspectj 模式与代理模式不同,aspectj 模式可以自身方法调用,也可以应用在非 public 方法上
进入类 AopAutoProxyConfigurer

在此着重分析代理模式的事务,AopAutoProxyConfigurer 是定义在 AnnotationDrivenBeanDefinitionParser 类中的一个内部类,其内部就一个静态方法。主要就是在容器中注册了四个 bean

private static class AopAutoProxyConfigurer {

   public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
      // 注册代理类(InfrastructureAdvisorAutoProxyCreator类型的bean)
      AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

      // TRANSACTION_ADVISOR_BEAN_NAME=org.springframework.transaction.config.internalTransactionAdvisor
      String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
      if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
         Object eleSource = parserContext.extractSource(element);

         // =============创建TransactionAttributeSource类型的bean.==============
         RootBeanDefinition sourceDef = new RootBeanDefinition(
               "org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
         sourceDef.setSource(eleSource);
         sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
         // 注册bean,并使用Spring中的定义规则生成beanName,返回beanName
         String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

         // =====================创建TransactionInterceptor类型的bean.=====================
         RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
         interceptorDef.setSource(eleSource);
         interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
         registerTransactionManager(element, interceptorDef);
         interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
         // 注册bean,并使用Spring中的定义规则生成beanName,返回beanName
         String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

         // ==============创建TransactionAttributeSourceAdvisor类型的bean.================
         RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
         advisorDef.setSource(eleSource);
         advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
         // 将sourceName的bean注入advisorDef的transactionAttributeSource属性中
         advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
         // 将interceptorName的bean注入advisorDef的adviceBeanName属性中
         advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
         // 如果配置了order属性,则加入到bean中
         if (element.hasAttribute("order")) {
            advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
         }
         // 注册TransactionAttributeSourceAdvisor类型的bean
         parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);

         // 创建CompositeComponentDefinition
         CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
         compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
         compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
         compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
         parserContext.registerComponent(compositeDef);
      }
   }
}

注册的四个 bean 分别是:

  • InfrastructureAdvisorAutoProxyCreator:自动代理创建器。事务自定义标签能够调用 AOP 方法的关键
  • TransactionAttributeSource:帮助解析事务注解信息,封装并保存成 TransactionAttribute
  • TransactionInterceptor:事务拦截器。在 AOP 的拦截器调用过程中接触过拦截器的概念,spring 会将所有的拦截器封装成 Advisors,最后会调用拦截器的 invoke() 方法进行目标方法增强等
  • TransactionAttributeSourceAdvisor:事务属性增强器。可见其属于增强器 Advisor 类型,其中可以定义切点表达式相关的内容

这四个 bean 支撑起了整个的事务功能

后置处理器的调用

上一部分我们主要工作就是注册了四个 beanDefinition,最终都会实例化成对应的 bean。我们简单的推测 spring 实现事务的原理,其实是通过 AOP 对我们的 service 方法进行增强,添加一些固定的流程代码,而实现这个逻辑基本和 AOP没有太大的差异,AOP 会在 bean 初始化的时候决定是否进行增强返回代理对象,实现这个功能主要靠的就是 BeanPostProcessor 后处理器接口方法。所以,事务也相似,我们先从 ProductInfoServiceImpl 的实例化代理对象创建着手,去分析事务的功能实现

ProductInfoServiceImpl 的代理对象创建

鉴于篇幅,本篇文章不再详细赘述 aop 代理对象的产生,我们直接进入 AbstractAutowireCapableBeanFactoryinitializeBean 方法

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		
		// 第一步:先执行所有的AwareMethods
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		} else {
			// 如果实现了Aware接口,就对该bean进行一些设置
        	// 比如实现了BeanNameAware接口,那么对其bean的属性beanName上设置对应的beanName
        	// 如果实现了BeanFactoryAware接口,那么对其beanFactory属性设置上创建该bean使用的bean工厂
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			// 执行所有的BeanPostProcessor#postProcessBeforeInitialization  初始化之前的处理器方法
			// 规则:只要谁反悔了null,后面的就都不要执行了
			// 这里面实现postProcessBeforeInitialization 的处理器就很多了,有很多对Aware进行了扩展的
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			// 如果bean实现了InitializingBean或者用户自定义的init方法方法,那么调用这些初始化方法对bean的属性进行一些个性化设置
			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()) {
			// 执行后置处理器的postProcessAfterInitialization方法。AOP的原理和实现就在其中
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
}
后处理器的调用

从代码中可以看出调用后处理器的方法其实是对所有的处理器都调用一遍,对我们构造出的 ProductInfoServiceImplbean 进行挨个后处理

/**
 * 初始化前应用BeanPostProcessors后处理器
 */
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
      throws BeansException {

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

/**
 * 初始化后应用BeanPostProcessors后处理器
 */
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {

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

第一部分的我们注册了一个 bean 后处理器 InfrastructureAdvisorAutoProxyCreator 就在这派上用场了。debug 代码截图如下,此时遍历的 beanProcessor 就是 InfrastructureAdvisorAutoProxyCreator 类型的实例

44935F9E-CE7F-1177-792E-51B5B846E019.png

AbstractAutoProxyCreatorpostProcessAfterInitialization() 方法

先看 postProcessAfterInitialization()接口方法,实现该方法是在 InfrastructureAdvisorAutoProxyCreator 的父类 AbstractAutoProxyCreator 中,实现 BeanPostProcessor接口方法,返回代理对象

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        // 如果是普通bean,则返回beanName,如果是FactoryBean,则返回加上前缀&的&beanName
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        // earlyProxyReferences中缓存的是已经创建好的代理对象
        if (!this.earlyProxyReferences.contains(cacheKey)) {
        	// 如果它适合被代理,则需要封装指定bean
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}
AbstractAutoProxyCreatorwrapIfNecessary 方法

看到这里,应该很熟悉了,之前在分析 AOP 流程的时候,也是这个方法。方法内容也无需多说,主要就是先寻找合适增强器,然后进行增强返回代理类对象

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    // 也是看看有没有缓存,有缓存对象就直接返回了
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    // 如果该bean不需要被代理,则直接返回原始的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;
    }
 	
 	// 获取 bean 的 advices(通知或增强器)
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
    	// 加入缓存中
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 通过createProxy方法创建代理对象
        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;
}
收藏 (0)
评论列表
正在载入评论列表...
我是有底线的
为您推荐
    暂时没有数据