Spring 源码解析(一)

2019-06-10  本文已影响0人  当年明月_3025

Spring 源码解析

概念

Spring 源码的核心组件:

IOC 容器可以理解为一个 Map,key 就是我们平常使用 Spring 框架时写的 Bean Id,value 就是对应类的实例化对象。

几个重要的类

在开始分析源码之前,我们先试着了解几个概念,这几个类对于我们理解源码有着很大的帮助,方便对整个 Spring 源码进行分析。

  1. ApplicationContext,BeanFactory
    提到 Spring 就一直说容器,这个容器我们上面也给出了一个直观的解释,可以理解为一个 Map,用来存储实例化的的对象,需要的时候就从容器里面取就可以了。那么在代码中的具体实现是什么那?

    大家最为熟悉的实现可能就是 ApplicationContext,它就是一个容器,而它实现了 BeanFactory 接口,可以说 BeanFactory 就是最基础的容器,ApplicationContext 相当于在 BeanFactory 接口增加了一些功能,它们都可以称为容器。

    先来看看 BeanFactory 的代码:

    public interface BeanFactory {
     String FACTORY_BEAN_PREFIX = "&";
    
     Object getBean(String var1) throws BeansException;
    
     <T> T getBean(String var1, @Nullable Class<T> var2) throws BeansException;
    
     Object getBean(String var1, Object... var2) throws BeansException;
    
     <T> T getBean(Class<T> var1) throws BeansException;
    
     <T> T getBean(Class<T> var1, Object... var2) throws BeansException;
    
     boolean containsBean(String var1);
    
     boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
    
     boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
    
     boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
    
     boolean isTypeMatch(String var1, @Nullable Class<?> var2) throws NoSuchBeanDefinitionException;
    
     @Nullable
     Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
    
     String[] getAliases(String var1);
        
    }
    

    整个接口定义的抽象方法其实非常简单和直接,主要就是各种个样的 getBean 方法和一些判断是否是单例或者原型的方法。

    再来看 ApplicationContext。

    public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
     @Nullable
     String getId();
    
     String getApplicationName();
    
     String getDisplayName();
    
     long getStartupDate();
    
     @Nullable
     ApplicationContext getParent();
    
     AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
    }
    

    不仅仅实现了 BeanFactory 接口,而且实现了事件派发器,资源解析器以及环境参数相关的接口,比 BeanFactory 多了许多功能。

    下面来看看常用的容器,也就是上面接口的实现类。

    • AnnotationConfigApplicationContext
      基于 @Configuration 注解配置类解析的容器。
    • ClassPathXmlApplicationContext
      基于类路径下 xml 文件配置解析的容器,如果用 xml 方式配置 Spring 框架,这个容器一定使用的非常多。
    • FileSystemXmlApplicationContext
      基于文件系统里的 xml 文件配置解析的容器。
    • GenericApplicationContext
      不太常用的 ApplicationContext,比上面两个更加灵活,可以读取任意配置方式的 Bean。
  2. BeanDefinition
    BeanDefinition 按照字面意思理解就是 Bean 的定义信息,我们从接口的定义来看看这个类到底保存了什么信息。

    public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
     String SCOPE_SINGLETON = "singleton";
     String SCOPE_PROTOTYPE = "prototype";
     int ROLE_APPLICATION = 0;
     int ROLE_SUPPORT = 1;
     int ROLE_INFRASTRUCTURE = 2;
    
     void setParentName(@Nullable String var1);
    
     @Nullable
     String getParentName();
    
     void setBeanClassName(@Nullable String var1);
    
     @Nullable
     String getBeanClassName();
    
     void setScope(@Nullable String var1);
    
     @Nullable
     String getScope();
    
     void setLazyInit(boolean var1);
    
     boolean isLazyInit();
    
     void setDependsOn(@Nullable String... var1);
    
     @Nullable
     String[] getDependsOn();
    
     void setAutowireCandidate(boolean var1);
    
     boolean isAutowireCandidate();
    
     void setPrimary(boolean var1);
    
     boolean isPrimary();
    
     void setFactoryBeanName(@Nullable String var1);
    
     @Nullable
     String getFactoryBeanName();
    
     void setFactoryMethodName(@Nullable String var1);
    
     @Nullable
     String getFactoryMethodName();
    
     ConstructorArgumentValues getConstructorArgumentValues();
    
     default boolean hasConstructorArgumentValues() {
         return !this.getConstructorArgumentValues().isEmpty();
     }
    
     MutablePropertyValues getPropertyValues();
    
     default boolean hasPropertyValues() {
         return !this.getPropertyValues().isEmpty();
     }
    
     boolean isSingleton();
    
     boolean isPrototype();
    
     boolean isAbstract();
    
     int getRole();
    
     @Nullable
     String getDescription();
    
     @Nullable
     String getResourceDescription();
    
     @Nullable
     BeanDefinition getOriginatingBeanDefinition();
    }
    
    

    从代码里看,BeanDefintion 里面保存了 Bean 的 Class 类名称,作用域【单例或者原型】,构造函数的参数,属性等等,这些信息也说明这个类是 Spring 用来构建 Bean 的主要的类。

    这个接口的主要实现类有 RootBeanDefinition,ChildBeanDefinition,GenericBeanDefinition等等。其中 RootBeanDefinition 最为常用,相当于 xml 文件中的 <bean> 标签,在 xml 中可以配置 parent 属性,这里的父就是 RootBeanDefinition,子就是 ChildBeanDefinition。

  3. BeanDefinitionRegistry
    既然有了材料 BeanDefinition,下面一定需要一个操作它的类,BeanDefinitionRegistry 就是一个用来帮我们操作 BeanDefinition 的接口,它的里面有许多操作 BeanDefinition 的方法,包括通过 BeanDefinition 注册 Bean 等等。

    public interface BeanDefinitionRegistry extends AliasRegistry {
     void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;
    
     void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
    
     BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
    
     boolean containsBeanDefinition(String var1);
    
     String[] getBeanDefinitionNames();
    
     int getBeanDefinitionCount();
    
     boolean isBeanNameInUse(String var1);
    }
    

    我们可以通过 registerBeanDefinition 方法将一个 Bean 注册到容器中。调用 BeanDefinitionRegistry.registerBeanDefinition 手工进行注册。

    BeanDefinitionRegistry registry = context.getRegistry();
    boolean definition = registry.containsBeanDefinition("person");
    
  4. BeanPostProcessor
    BeanPostProcessor,bean 的后置处理器,在 bean 初始化前后进行一些处理工作。postProcessBeforeInitialization:在初始化之前
    工作。postPorcessAfterInitialization:在初始化之后工作。

    
    public interface BeanPostProcessor {
     @Nullable
     default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
         return bean;
     }
    
     @Nullable
     default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
         return bean;
     }
    }
    

    由此衍生出来的后置处理器非常多,处理时机也不一样,我们会在后面的源码分析对这些后置处理器的实现原理和操作时机进行一个总结。
    Spring 底层对 BeanPostProcessor 的使用:bean 赋值,注入其他组件,@Autowired,声明周期注解功能,@Async等等。

  5. ApplicationContextAware
    自定义组件想要使用 Spring 容器底层的一些组件(ApplicationContext,BeanFactory,xxx)等等,需要自定义组件实现 xxxAware 接口。在创建对象的时候,会调用接口规定的方法注入相关组件。ApplicationContextAware 会将 IOC 容器传入到组件中,BeanNameAware 会讲当前实例在 IOC 容器中 Bean 的名字传入到实例中。这些 Aware 会有对应的 AwareProcessor 来进行逻辑处理。

    public interface ApplicationContextAware extends Aware {
     void setApplicationContext(ApplicationContext var1) throws BeansException;
    }
    

    如果想往组件中注入容器可以实现 ApplicationContextAware 接口,然后通过 setApplicationContext 保存起来。 我们对 Spring 功能进行扩展时常常哟昂到这些 Aware。

  6. ApplicationListener 与 ApplicationEventMulticaster
    这两个组件是 Spring 事件驱动模型用到的组件,ApplicationListener:事件监听。ApplicationEventMulticaster:事件派发。

Bean 的生命周期

Bean 的声明周期指的是 Bean 的创建-->初始化-->销毁的过程,Spring 把这个过程全部交给容器来管理。我们可以自定义初始化和销毁方法,容器在 Bean 进行到当前生命周期的时候来调用我们自定一的初始化和销毁方法。

构造(对象创建)
单实例:在容器启动的时候创建对象。
多实例:在每次获取的时候创建对象,调用 getBean 方法时。

初始化
对象创建完成,并赋值好,调用初始化方法

销毁
单实例:容器关闭的时候。
多实例:容器会创建 Bean, 但不会管理 Bean,容器不会调用销毁方法。

Bean 的生命周期要比上面写的更加复杂,我们在分析完源码后会对这部分进行一个总结。

几个重要的注解

@Import,快速给容器中导入一个组件,@Import(Color.class) 相当于一个无参构造函数。id 默认是全类名。

@Conditional 满足一定条件才给容器中注册bean,这个可以用来让两个bean形成依赖,可以用在方法上,也可以用在类上。这个注解在 SpringBoot 用的非常多。

最后说说 @Autowired 和 @Resource 的区别:
@Autowired 自动注入默认按照 type 注入,即按照 .class 查找。如果找到多个相同类型的组件,在将属性的名称作为组件的 id 去容器中查找。使用 @Qualifier("bookDao") 与 @Autowired 组合可以明确指定需要装配的 Bean,通过 id。
@Autowired(require=false) 有就装配,没有就变为 null。

Spring 还支持 JSR250 和 JSR330 里的 @Resource 和 @Inject 注解。Java 规范的注解。@Resource 和 @Autowired 一样实现自动装配,默认按照属性名称进行自动装配。不支持 @Primary,也不支持 @Autowired(require=false)。
@Inject 需要额外导入包,功能和 @Autowired 一样,不支持 require=false;
@Autowired 可以标注在构造器、参数、方法、属性上。

提出问题

有了一些概念后,我们心里一定会有一些问题,同时带着问题去看源码也有助于我们更加快速地切入到 Spring 得核心,不墨迹,直给。

  1. 容器时怎么创建得,创建时都要做哪些工作。
  2. Spring 为什么要用 BeanDefintion 去构造 Bean。
  3. Spring 用 BeanDefintion 去构建 Bean 得流程是什么?
  4. Spring AOP 在 Spring 框架得基础上做了什么?

下面我们带着问题去看看源码。

容器创建和初始化过程

还是从下面这段代码开始

AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Config.class);

new 容器的过程到底执行了什么操作那?前两步是预处理和配置类的解析工作,我们直接看 refresh 方法,这个方法就是容器的创建和刷新以及 Bean 初始化的核心方法。

public AnnotationConfigApplicationContext(Class... annotatedClasses) {
  this();
  this.register(annotatedClasses);
  this.refresh();
}

refresh() 核心方法:

public void refresh() throws BeansException, IllegalStateException {
  synchronized(this.startupShutdownMonitor) {
    this.prepareRefresh();
    ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
    this.prepareBeanFactory(beanFactory);

    try {
      this.postProcessBeanFactory(beanFactory);
      this.invokeBeanFactoryPostProcessors(beanFactory);
      this.registerBeanPostProcessors(beanFactory);
      this.initMessageSource();
      this.initApplicationEventMulticaster();
      this.onRefresh();
      this.registerListeners();
      this.finishBeanFactoryInitialization(beanFactory);
      this.finishRefresh();
    } catch (BeansException var9) {
      if (this.logger.isWarnEnabled()) {
        this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
      }

      this.destroyBeans();
      this.cancelRefresh(var9);
      throw var9;
    } finally {
      this.resetCommonCaches();
    }

  }
}
  1. prepareRefresh() 刷新前的预处理
  1. obtainFreshBeanFactory() 获取 Bean 工厂。
  1. prepareBeanFactory(),BeanFactory 的预准备工作,BeanFactory 进行一些设置。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
  beanFactory.setBeanClassLoader(this.getClassLoader());
  beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
  beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
  beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
  beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
  beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
  beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
  beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
  beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
  beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
  beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
  beanFactory.registerResolvableDependency(ResourceLoader.class, this);
  beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
  beanFactory.registerResolvableDependency(ApplicationContext.class, this);
  beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
  if (beanFactory.containsBean("loadTimeWeaver")) {
    beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
    beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
  }

  if (!beanFactory.containsLocalBean("environment")) {
    beanFactory.registerSingleton("environment", this.getEnvironment());
  }

  if (!beanFactory.containsLocalBean("systemProperties")) {
    beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
  }

  if (!beanFactory.containsLocalBean("systemEnvironment")) {
    beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
  }

}
  1. postProcessBeanFactory,BeanFactory 准备工作完成后进行的后置处理工作,子类通过重写这个方法来在 BeanFactory 创建并预备完成以后做进一步的设置。

=============================以上是 BeanFactory 创建及准备================================

  1. invokeBeanFactoryPostProcessors(beanFactory),执行 BeanFactoryPostProcessor。

BeanFactoryProcessor:BeanFactory 的后置处理器,在 BeanFactory 标准初始化执行的 Processor,标准初始化就是以上四部。

两个主要接口,BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor(可以用这个来注册一些新的组件 )。

执行 BeanPostProcessor 的方法:

先执行 BeanDefintionRegistryPostProcessor

在执行 BeanFactoryPostProcessor 的方法

  1. registerBeanPostProcessors,注册 BeanPostProcessor,Bean 的后置处理器【拦截 Bean 的创建过程】。

不同接口类型的 BeanPostProcessor,在 Bean 创建前后的执行时机是不一样的。

BeanPostProcessor

DestructionAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor

SmartInstantiationAwareBeanPostProcessor

MergedBeanDefinitionPostProcessor【internalPostProcessors】

  1. initMessageSource,初始化 MessageSource 组件,做国际化消息,消息绑定,消息解析。
  1. initApplicationEventMulticaster,初始化事件派发器。
  1. onRefresh,留给子容器(子类),重写 onRefresh 方法,在容器刷新时可以再自定义逻辑。

  2. registerListeners,给容器中把项目里的 ApplicationListener 注册进来。

  1. finishBeanFactoryInitialization,初始化所有剩下的单实例 Bean。
//初始化所有剩下的单实例 bean。
beanFactory.preInstantiateSingletons();
- 缓存中获取不到,开始 Bean 的创建对象流程。

- 标记当前 Bean 已经被创建。

- 获取 Bean 的定义信息。

- 获取当前 Bean 所依赖的其他 Bean,如果有就按照 getBean() 把依赖的 Bean 先创建出来。

- 启动单实例 Bean 的创建流程。

  ```java
  createBean(beanName,mbd,args);
  
  //让 BeanPostProcessor 拦截返回对象。正常的 BeanPostProcessor 是对象创建完成初始化之前执行的,而这个 BeanPostProcessor 要在 Bean 创建之前执行
  
  //InstantiationAwareBeanPostProcessor 提前执行
  //触发 postProcessBeforeInstantiation 方法
  //如果上一步有返回值,在触发 postProcessAfterInitialization 方法
  Object bean = resolveBeforeInstantiation(beanName,mbdToUse);
  ```

  如果 InstantiationAwareBeanPostProcessor 没有返回代理对象,调用下面的方法创建 Bean。

  ```java
  Object beanInstance = doCreateBean(beanName,mbcToUse,args);
  
  //创建 Bean 实例,利用工厂方法或者对象的构造器创建出 Bean 实例。
  createBeanInstance(beanName,mbd,args);
  
  // 创建实例对象后,执行后置处理器
  // 利用 MergedBeanDefintionPostProcessor 
  applyMergedBeanDefintionPostProcessor(mbd,beanType,beanName);
  bdp.postProcessMergedBeanDefinition(mbd,beanType,beanName);
  ```

  对 Bean 的属性进行赋值

  ```java
  populateBean(beanName,mbd,instanceWrapper);
  
  //赋值之前拿到 InstantiationAwareBeanPostProcessor 后置处理器
  //执行 postProcessAfterInstantiation
  
  //再拿 InstantiationAwareBeanPostProcessor 后置处理器
  //执行 postProcessPropertyValues 方法
  
  //最后一步,应用 Bean 属性的值,利用 setter 方法等用反射赋值。
  applyPropertyValues(beanName,mbd,bw,pvs);
  ```

  对 Bean 进行初始化

  ```java
  initializeBean(beanName,exposedObject,mbd);
  
  //执行 Aware 接口的方法
  //判断是否是 BeanNameAware,BeanClassLoaderAware,BeanFactoryAware,利用 invoke 回调接口的方法。
  invokeAwareMethods(beanName,bean);
  
  //执行所有后置处理器初始化之前的方法
  applyBeanPostProcessorsBeforeInitialization(wrapperBean)
  //执行后置处理器的回调方法
  BeanPostProcessor.postProcessBeforeInitialization()
    
  //执行初始化方法
  invokeInitMethods(beanName,wrappedBean,mbd);
  //是否是 InitializingBean 接口实现类,执行接口规定的初始化。
  //是否自定义初始化方法。
  
  //执行初始化之后后置处理器的方法
  applyBeanPostProcessorsAfterInitialization(wrapperBean)
  //执行后置处理器的回调方法
  BeanPostProcessor.postProcessAfterInitialization()
  ```

  注册 Bean 的销毁方法。不执行方法,在容器销毁时执行。

- ·将创建的 Bean 添加到缓存 singletonObjects 中。IOC 容器就可以理解为这些 Map,这些 Map 里面保存了很多单实例 Bean,环境信息。
  1. finishRefresh 完成 BeanFactory 初始化创建工作,IOC 容器创建完成。

总结:

Spring 创建 Bean 的时机:

  1. 用到这个 Bean 的时候,利用 getBean 创建 bean 后保存到容器中。
  2. 同一创建所有剩下的 bean 的时候,finishBeanFactoryInitialization();

后置处理器:

每一个 Bean 创建完成后,都会使用各种后置处理器进行处理,来增强 Bean 的功能。

  1. AutowiredAnnotationBeanPostProcessor:来处理自动注入。
  2. AnnotationAwareAspectJAutoProxyCreator:来做 AOP 功能。
  3. AsyncAnnotationBeanPostProcessor:增强功能注解。

AOP原理

整体启动流程:

第一步

从 @EnableAspectJAutoProxy 开始分析。首先关注 @Import,将 AspectJAutoProxyRegistrar,给容器中导入 AspectJAutoProxyRegistrar。AspectJAutoProxyRegistrar 又实现了 ImportBeanDefinitionRegistrar 接口,这个接口可以自定义注册 Bean。

@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy{}

AnnotationMetadata:当前类的注解信息。

BeanDefinitionRegistry:BeanDefinition注册类。

//ImportBeanDefinitionRegistrar
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry){
    //根据class指定BeanDefintion信息
        RootBeanDefinition beanDefinition = new RootBeanDefinition(A.class);
        //注册一个 Bean,指定 bean 名称
        registry.registerBeanDefintion("rainBow",beanDefinition)
}

@EnableAspectJAutoProxy 利用 AspectJAutoProxyRegistrar 自定义给容器中注册 Bean。那么它为 AOP 注册了什么 Bean 那?

可以在 AspectJAutoProxyRegistrar 的 registerBeanDefinitions 函数里寻找答案:

//AspectJAutoProxyRegistrar
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//想容器中注册了一个名为 internalAutoProxyCreator,class 为 AnnotationAwareAspectJAutoProxyCreator 的 Bean。BeanDefinitionRegistry.registerBeanDefinition
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
  
//拿到注解相关的信息  
        AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
//根据拿到的注解的信息判断 proxyTargetClass 和 exposeProxy 属性
        if (enableAspectJAutoProxy != null) {
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }

            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }

    }

第一步总结:利用 AspectJAutoProxyRegistrar 给容器中注册了一个 AnnotationAwareAspectJAutoProxyCreator 类型的 Bean。

第二步

既然住了一个 AnnotationAwareAspectJAutoProxyCreator,那么这个组件有什么作用那?字面理解这个 Bean 是注解模式切面自动代理创建器。

先来看这个组件的继承关系:

AnnotationAwareAspectJAutoProxyCreator

​ ->AspectJAwareAdvisorAutoProxyCreator

​ ->AbstractAdvisorAutoProxyCreator

​ ->AbstractAutoProxyCreator

​ implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware

最源头实现了一个 Bean 后置处理器的接口和一个 BeanFactory 的接口。后置处理器在 Bean 初始化完成前后做事情,自动装配 BeanFactory 到实例中。首先看看这两个接口对应的 set 方法在哪里实现的。

AbstractAutoProxyCreator.setBeanFactory()

AbstractAutoProxyCreator.后置处理器相关的逻辑

AspectJAwareAdvisorAutoProxyCreator.setBeanFactory()->initBeanFactory()

AnnotationAwareAspectJAutoProxyCreator.initBeanFactory(),父类调用 setBeanFactory 的时候会调用 initBeanFactory 方法,这个方法又被子类重写了,最后还会调用子类的 initBeanFactory 方法。

AspectJAwareAdvisorAutoProxyCreator【InstantiationAwareBeanPostProcessor】的作用:

总结:

Spring 事务

入口与 AOP 一样,通过 @EnableTransactionManagement 来进行源码分析。

@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement{
      boolean proxyTargetClass() default false;
      AdviceMode mode() default AdviceMode.PROXY;
}

这个注解同样有 @Import 注解,我们来关注 TransactionManagementConfigurationSelector 这个类来看到底为 Spring 事务导入了什么组件。

protected String[] selectImports(AdviceMode adviceMode) {
  switch(adviceMode) {
    case PROXY:
      return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
    case ASPECTJ:
      return new String[]{"org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration"};
    default:
      return null;
  }
}

从上面这段代码可以看出,这个注解为我们导入两个组件,AutoProxyRegistrar 和 ProxyTransactionManagementConfiguration。

我们依次来看这两个组件就能明白 Spring 事务到底是怎么实现的了。

AutoProxyRegistrar

public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

  public AutoProxyRegistrar() {
  }
  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
                   Object proxyTargetClass = candidate.get("proxyTargetClass");
                if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() && Boolean.class == proxyTargetClass.getClass()) {
                    candidateFound = true;
                    if (mode == AdviceMode.PROXY) {
                        AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                        if ((Boolean)proxyTargetClass) {
                            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                            return;
                        }
                    }
                }
    }
}

从代码来看,他实现了 ImportBeanDefinitionRegistrar 接口,功能就不用解释了,调用 registerBeanDefinitions 方法给容器中注册 Bean 的。

因为 EnableTransactionManagement 里定义的 mode 就是 AdviceMode.PROXY,而且 proxyTargetClass 是false,所以会执行如下代码:

AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);

给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件,这个组件也是一个后置处理器。

作用:利用后置处理器机制,在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法,利用连接器链进行调用。

ProxyTransactionManagementConfiguration

@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    public ProxyTransactionManagementConfiguration() {
    }

    @Bean(
        name = {"org.springframework.transaction.config.internalTransactionAdvisor"}
    )
    @Role(2)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionAttributeSource(this.transactionAttributeSource());
        advisor.setAdvice(this.transactionInterceptor());
        if (this.enableTx != null) {
            advisor.setOrder((Integer)this.enableTx.getNumber("order"));
        }

        return advisor;
    }

    @Bean
    @Role(2)
    public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource();
    }

    @Bean
    @Role(2)
    public TransactionInterceptor transactionInterceptor() {
        TransactionInterceptor interceptor = new TransactionInterceptor();
        interceptor.setTransactionAttributeSource(this.transactionAttributeSource());
        if (this.txManager != null) {
            interceptor.setTransactionManager(this.txManager);
        }

        return interceptor;
    }
}

首先 ProxyTransactionManagementConfiguration 也是一个配置类,利用 @Bean 给容器中注册了一些组件。

首先注册了一个 BeanFactoryTransactionAttributeSourceAdvisor 事务增强器。事务增强器需要注解里面信息。

我们关注代码中注册时需要传入一个事务属性,这个属性在下面也是注入的一个 Bean。

advisor.setTransactionAttributeSource(this.transactionAttributeSource());

@Bean
@Role(2)
public TransactionAttributeSource transactionAttributeSource() {
  return new AnnotationTransactionAttributeSource();
}

AnnotationTransactionAttributeSource 注册了好多的注解解析器来支持各种类型的注解,包扩 Spring 注解,Jta 注解,Ejb3 注解等等。

public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
  this.publicMethodsOnly = publicMethodsOnly;
  this.annotationParsers = new LinkedHashSet(2);
  this.annotationParsers.add(new SpringTransactionAnnotationParser());
  if (jta12Present) {
    this.annotationParsers.add(new JtaTransactionAnnotationParser());
  }

  if (ejb3Present) {
    this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
  }

}

接下来看事务增强器的第二个属性,事务拦截器,这个属性也是下面注册的一个 Bean。

advisor.setAdvice(this.transactionInterceptor());

@Bean
@Role(2)
public TransactionInterceptor transactionInterceptor() {
  TransactionInterceptor interceptor = new TransactionInterceptor();
  interceptor.setTransactionAttributeSource(this.transactionAttributeSource());
  if (this.txManager != null) {
    interceptor.setTransactionManager(this.txManager);
  }

  return interceptor;
}

扩展组件

BeanFactoryPostProcessor

我们以前了解过 BeanPostProcessor,它们之间有什么区别那?

BeanPostProcessor:bean 后置处理器,bean 创建对象初始化前后进行拦截工作的。

BeanFactoryPostProcessor:beanFactory 的后置处理器,在 BeanFactory 标准初始化之后调用,所有的 BeanDefifnition 都已经保存加载到 beanFactory 中,但是 bean 的实例还未创建。

如何找到所有的 BeanFactoryPostProceessor 并执行它们的方法:

BeanDefinitionRegistryPostProcessor

可以将 BeanDefinitionRegistry 理解为 BeanDefinition 的保存中心,以后 BeanFactory 按照 BeanDefinitionRegistry 里面保存的每一个 bean 定义信息创建 bean 的实例。

下面我们来看 BeanFactoryPostProcessor 的子接口:

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}

额外定义了一个 postProcessBeanDefinitionRegistry 方法,在所有 bean 的定义信息将要被加载,bean 实例还未被创建时执行,在 BeanFactoryPostProceessor 之前执行,因为 BeanFactoryPostProceessor 是在 bean 的定义信息已经被加载后执行。

可以利用 BeanDefinitionRegistryPostProcessor 给容器中额外添加一些组件。

原理:

ApplicationListener

监听容器中发布的事件,完成事件驱动模型的开发。

public interface ApplicationListener<E extends ApplicationEvent>

监听 ApplicationEvent 及其子类。

基于事件开发的步骤:

原理:

ContextRefreshEvent 事件

SmartInitializingSingleton

所有单实例 Bean 创建完成之后触发。

// 所有的单实例 Bean 创建完后执行
public interface SmartInitializingSingleton{
  void afterSingletonsInstantiated();
}

过程:

上一篇 下一篇

猜你喜欢

热点阅读