美文网首页
Spring 源码解析(一)

Spring 源码解析(一)

作者: 当年明月_3025 | 来源:发表于2019-06-10 21:55 被阅读0次

Spring 源码解析

  • 第一章为源码解析。
  • 第二章为实现一个简单的 IOC 容器。
  • 第三章进阶 Spring 插件开发。

概念

Spring 源码的核心组件:

  • IOC 容器负责实例化,定位,配置应用程序中的对象及建立这些对象间的依赖。
  • AOP 面向切面编程,通过预编译方式和运行期间动态代理实现功能的统一维护的一种技术。

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() 刷新前的预处理
  • initPropertySources,字面上理解就是初始化一些属性,但是方法体是空的,留给子类去实现。子类可以自定义个性化属性设置方法。
  • getEnvironment().validateRequiredProperties(),属性校验。
  • earlyApplicationEvents,用来保存容器中的一些早期的事件。等事件派发器初始化好了之后再把它们派发出去。
  1. obtainFreshBeanFactory() 获取 Bean 工厂。
  • refreshBeanFactory(),刷新【创建】 BeanFactory。

    在 GenericApplicationContext 里无参构造器创建一个 BeanFactory 对象。

    this.beanFactory = new DefaultListableBeanFactory();
    

    设置一个 Id。

  • getBeanFactory(),返回刚才 GenericApplicationContext 创建的 BeanFactory 对象。刚创建,里面都是默认的配置。

  • 将创建的 BeanFactory【DefaultListableBeanFactory】返回。

  1. prepareBeanFactory(),BeanFactory 的预准备工作,BeanFactory 进行一些设置。
  • 设置 BeanFactory 的类加载器、支持表达式解析器。。。

  • 添加 部分的BeanPostProcessor【ApplicationContextAwareProcessor】

  • 设置忽略自动装配的接口,EnvironmentAware、EmbeddedValueResolverAware。。。

  • 注册可以解析的自动装配,我们可以在任何组件中自动注入,ResourceLoader,BeanFactory,ApplicationContext。

  • 添加 BeanPostProcessor【ApplicationListenerDetector】。

  • 添加编译时的 AspectJ。

  • 给 BeanFactory 中注册一些能用的组件。

    environment

    systemProperties

    systemEnvironment

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

  • 获取所有的 BeanDefinitionRegistryPostProcessor。

  • 对于实现了 PriorityOrdered 优先级接口的 BeanDefinitionRegistryPostProcessor

    postProcessor.postProcessBeanDefinitionRegistry(registry)

  • 对于实现了 Ordered 顺序接口的 BeanDefinitionRegistryPostProcessor

    postProcessor.postProcessBeanDefinitionRegistry(registry)

  • 最后执行没有实现任何优先级或者是顺序接口的 BeanDefinitionRegistryPostProcessor

    postProcessor.postProcessBeanDefinitionRegistry(registry)

在执行 BeanFactoryPostProcessor 的方法

  • 流程和 BeanDefinitionRegistryPostProcessor 一模一样。
  1. registerBeanPostProcessors,注册 BeanPostProcessor,Bean 的后置处理器【拦截 Bean 的创建过程】。

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

BeanPostProcessor

DestructionAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor

SmartInstantiationAwareBeanPostProcessor

MergedBeanDefinitionPostProcessor【internalPostProcessors】

  • 获取所有的 BeanPostProcessor,后置处理器都默认可以有 PriorityOrdered,Ordered 来指定优先级。

  • 先注册 PriorityOrdered 优先级接口的 BeanPostProcessor,把每一个 BeanPostProcessor 添加到 BeanFactory 中。

    beanFactory.addBeanPostProcessor(postProcessor)
    
  • 再注册 Ordered 接口的。

  • 最后注册没有实现任何优先级接口的。

  • 最终注册,MergedBeanDefinitionPostProcessor。

  • 注册一个 ApplicationListenerDetector,来在 Bean 创建完成后检查是否是 ApplicationListener,如果是

    applicationContext.addApplicationListener((ApplicationListener<?>) bean);
    
  1. initMessageSource,初始化 MessageSource 组件,做国际化消息,消息绑定,消息解析。
  • 获取 BeanFactory。

  • 判断容器有没有 id 为 messageSource 的,类型是 MessageSource 的组件

    如果有赋值给 messageSource 属性,如果没有自己创建一个 DelegatingMessageSource。

    MessageSource 取出国际化配置文件中的某个 key 值,能按照区域信息获取。

  • 把创建好的 MessageSource 注册到容器中,以后获取国际化配置文件的值的时候,可以自动注入 MessageSource,调用 getMessage 方法就可以获取到了。

    beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource)
    
  1. initApplicationEventMulticaster,初始化事件派发器。
  • 获取 BeanFactory。
  • 从 BeanFactory 中获取 ID 为 applicationEventMulticaster,类型为 ApplicationEventMulticaster 的派发器。
  • 如果上一步没有配置事件派发器,就创建一个 SimpleApplicationEventMulticaster,为我们派发事件。
  • 将创建的 ApplicationEventMulticaster 添加到 BeanFactory 中,以后其他组件自动注入即可。
  1. onRefresh,留给子容器(子类),重写 onRefresh 方法,在容器刷新时可以再自定义逻辑。

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

  • 从容器中拿到所有的 ApplicationListener 组件,将每个监听器添加到事件派发器中。

    getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName)
    
  • 派发之前步骤产生的事件,派发器没初始化之前的。

  1. finishBeanFactoryInitialization,初始化所有剩下的单实例 Bean。
//初始化所有剩下的单实例 bean。
beanFactory.preInstantiateSingletons();
  • 获取容器中的所有 BeanDefinitions,依次进行初始化和创建对象。

  • 如果 Bean 不是抽象的,是单实例,不是懒加载的,就开始创建单例 Bean。

    判断是否是 FactoryBean,即是否实现了 FactoryBean 接口的 Bean,如果是就用工厂方法创建对象。

    如果不是工厂 Bean,利用 getBean(beanName) 创建对象。

    • getBean(beanName),就是自己写测试类的那个 getBean。

    • 调用 doGetBean(name,null,null,false)。

    • 先获取缓存中保存的单实例 Bean,如果能获取到说明这个 Bean 之前被创建过了(所有创建过的单实例 Bean 都会被缓存起来)。

      //保存单实例 Bean 的
      private final Map<String,Object> singletonObjects = new ConcurrentHashMap<String,Object>(256);
      
- 缓存中获取不到,开始 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,环境信息。
  • 检查所有 Bean 是否实现了 SmartInitializingSingleton 接口,如果是,就执行回调方法。
  1. finishRefresh 完成 BeanFactory 初始化创建工作,IOC 容器创建完成。
  • 初始化和声明周期有关的后置处理器

    initLifecycleProcessor();
    
    //先从容器中找,找不到 new 一个 Default 的,并且注册在 BeanFactory 中,可以注入到组件中。
    //允许写 LifecycleProcessor, 可以在 BeanFactory 刷新完成或者关闭时调用一些方法。
    void onRefresh();
    void onClose();
    
  • 拿到前面定义的生命周期处理器,回调 onRefresh 方法。

  • 发布容器刷新完成事件。

    publishEvent(new ContextRefreshedEvent(this));
    

总结:

Spring 创建 Bean 的时机:

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

后置处理器:

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

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

AOP原理

整体启动流程:

  • 传入配置类,创建 IOC 容器。

  • 注册配置类,调用 refresh() 刷新容器。

  • registerBeanPostProcessors(beanFacotry),注册 Bean 的后置处理器方便拦截 Bean 的创建。

    • 获取 IOC 容器中已经定义了的需要创建对象的所有 BeanPostProcessor,配置类里注册的。

    • 给容器中加其他的 PostProcessor。

    • 优先注册了实现了 PriorityOrdered 接口的 BeanPostProcessor。

    • 再给容器中注册实现了 Ordered 接口的 BeanPostProcessor。

    • 最后注册没实现优先级接口的 BeanPostProcessor。

    • 注册 BeanPostProcessor,实际上就是创建 BeanPostProcessor 的对象并保存在容器中。

    • 创建 internalAutoProxyCreator 的 BeanPostProcessor[AnnotationAwareAspectJAutoProxyCreator]

      • 创建 Bean 的实例
      • populateBean:给 Bean 的属性赋值
      • initializeBean:初始化 Bean
        • invokeAwareMethods():处理 Aware 接口的方法回调。
        • applyBeanPostProcessorsBeforeInitialization():应用后置处理器的 postProcessBeforeInitialization 方法。
        • invokeInitMethods():执行自定义初始化方法。
        • applyBeanPostProcessorsAfterInitialization():执行后置处理器的 PostProcessAfterInitialization 方法。
      • BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator) 创建成功。调用 initBeanFactory 生成 aspectJAdvisorsBuilder。
    • 把 BeanPostProcessor 注册到 BeanFactory 中:

      beanFactory.addBeanPostProcessor(postProcessor)。

    ==========以上是创建和注册 AnnotationAwareAspectJAutoProxyCreator 的过程=========

    AnnotationAwareAspectJAutoProxyCreator 这个 BeanPostProcessor 做了什么?

    看给容器中注册了什么组件,这个组件什么时候工作,有什么功能?

    AnnotationAwareAspectJAutoProxyCreator => InstantiationAwareBeanPostProcessor

  • finishBeanFactoryInitialization(beanFactoty),完成 BeanFactory 的初始化工作,创建剩下的单实例 Bean。

    • 遍历获取容器中所有的 Bean,依次创建对象 getBean(beanName)。

    getBean->doGetBean()->getSingleton()

    • 创建 Bean

      【AnnotationAwareAspectJAutoProxyCreator 在所有 Bean 创建之前会有一个拦截,因为实现了InstantiationAwareBeanPostProcessor,会调用 postProcessBeforeInstantiation 方法】

      • 先从缓存中获取当前 Bean,如果能获取到,说明 Bean 是之前被创建过的,直接使用,否则再创建。只要创建好的 Bean 都会被缓存起来。

      • createBean(),创建 Bean。AnnotationAwareAspectJAutoProxyCreator 会在任何 Bean 创建之前尝试返回 Bean 的实例。

        【BeanPostProcessor 是在 Bean 对象创建完成初始化前后调用的】

        【InstantiationAwareBeanPostProcessor 是在创建 Bean 实例之前尝试用后置处理器返回对象的】

        • resolveBeforeInstantiation(beanName,mbdToUse),解析 BeforeInstantiation。希望后置处理器在此能返回一个代理对象。如果能返回代理对象就使用,如果不能就继续。

        • resolveBeforeInstantiation 方法里,后置处理器先尝试返回对象。

          bean = applyBeanPostProcessorsBeforeInstantiation,拿到所有后置处理器,如果是 InstantiationAwareBeanPostProcessor,就执行后置处理的 postProcessBeforeInstaniation 方法。

          if(bean != null){

          ​ bean = applyBeanPostProcessorsAfterInitialization

          }

        • doCreateBean(beanName,mbdToUse,args),真正的去创建一个 Bean 实例。

第一步

从 @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】的作用:

  • 每个 Bean 创建之前,调用 postProcessBeforeInstantiation 方法。

    关心我们加入切面的 Bean

    • 判断当前 Bean 是否在 advisedBeans 中(保存了所有需要增强的 Bean)。
    • 判断当前 Bean 是否是基础类型,Advice、Pointcut、Advisor、AopInfrastructureBean,或者是否是切面( @Aspect 注解)
    • 判断是否需要跳过,获取候选的增强器(切面里的通知方法),每一个封装的通知方法的增强器是 InstantiationModelAwarePointcutAdvisor,判断每一个增强器是否是 AspectJPointcutAdvisor 类型。
  • 创建对象。

  • Bean 创建之后,调用 postProcessAfterInitialization 方法。

    return wrapIfNecessary(bean, beanName,cacheKey); //包装如果需要的情况下

    • 获取当前 Bean 的所有增强器(通知方法)。找到能在当前 Bean 使用的增强器(哪些通知方法是要切入当前 Bean 方法的)。然后给增强器排序。

    • 保存当前 Bean 到 advisedBean,表示当前 Bean 已经被增强了。

    • 创建当前 Bean 的代理对象,通过 proxyFactory 创建代理对象。需要传入增强器。通过 proxyFactory 会创建两种动态代理。

      JdkDynamicAopProxy(config); jdk 动态代理。实现了接口就用jdk。

      ObjenesisCglibAopProxy(config); cglib 的动态代理。

    wrapIfNecessary 执行结束,给容器中返回当前组件使用 cglib 增强了的代理对象。以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程。

  • 目标方法执行。

    容器中保存了组件的代理对象(jdk 或 cglib 增强后的),这个兑现管理保存了详细信息,比如增强器,目标对象。

    • CglibAopProxy.intercept() 方法,拦截目标方法执行。

    • 根据 ProxyFactory 获取对象将要执行的目标方法连接器链 chain。

      List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

      List<Object> interceptorList 保存所有拦截器,一个默认的 ExposeInvocationInterceptor 和 自定义的增强器

      遍历所有的增强器,将其转为 Interceptor,registry.getIntercepotr(advisor)

      如果是 MethodInterceptor,直接加入集合,如果不是,使用 AdvisorAdapter 将其增强转为 MethodInterceptor。

    • 如果没有拦截器链,直接执行目标方法。

      拦截器链:每一个通知方法又被包装为方法拦截器,利用 MethodInterceptor 机制来执行方法。

    • 如果有拦截器链,把需要执行的目标对象,目标方法,连接器链等信息传入创建一个 CglibMethodInvocation 对象,并调用 procceed 方法,返回 retVal。

    • 拦截器链的触发过程

      如果没有拦截器执行目标方法,最后一个拦截器也执行目标方法。

  • 链式获取每一个拦截器,拦截器执行 invoke 方法,每一个连接器等待下一个拦截器执行完成返回以后再执行,拦截器链的机制,保证通知方法与目标方法的执行顺序。

总结:

  • 使用 @EnableAspectJAutoProxy 开启 AOP 功能。

  • @EnableAspectJAutoProxy 会给容器中注册一个组件 AnnotationAwareAspectJAutoProxyCreator。

  • AnnotationAwareAspectJAutoProxyCreator 是一个后置处理器。

  • 容器的创建过程:

    • registerBeanPostProcessors() 注册后置处理器: 创建 AnnotationAwareAspectJAutoProxyCreator 对象。

    • finishBeanFactoryInitialization() 初始化剩下的单实例 Bean。

      • 创建业务逻辑组件和切面组件。

      • AnnotationAwareAspectJAutoProxyCreator 会拦截组件的创建过程。

      • 组件创建完后,判断组件是否需要增强

        是:切面的通知方法,包装成增强器(Advisor),给业务逻辑创建一个代理对象。

    • 执行目标方法

      • 代理对象执行目标方法

      • 用 CglibAopProxy.intercept 进行拦截。

        • 得到目标方法的拦截器链(增强器包装成拦截器 MethodInterceptor)。

        • 利用拦截器的链式机制,依次进入每一个拦截器进行执行。

        • 效果:

          前置通知->目标方法->后置通知->返回通知/异常通知

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 的实例还未创建。

  • IOC 容器创建对象

  • invokeBeanFactoryPostProcessors(beanFactory)。

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

  • 直接在 BeanFactory 中找到所有类型是 BeanFactoryPostProcessor 的组件,并执行它们的方法。
  • 在初始化创建其他组件前面执行。

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 给容器中额外添加一些组件。

原理:

  • IOC 创建对象
  • refresh()->invokeBeanFactoryPostProcessors(beanFactory);
  • 先从容器中获取到所有的 BeanDefinitionRegistryPostProcessors 组件,依次触发所有的 postProcessBeanDefinitionRegistry() 方法,再触发 BeanFactoryPostProcessor。
  • 再来从容器中找到 BeanFactoryPostProcessor 组件,一次触发 postProcessBeanFactory() 方法。

ApplicationListener

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

public interface ApplicationListener<E extends ApplicationEvent>

监听 ApplicationEvent 及其子类。

基于事件开发的步骤:

  • 写一个监听器来监听某个事件,ApplicationEvent 及其子类。

  • 或者使用 @EventListener 注解让任意组件都能监听事件,使用 EventListenerMethodProcessor 这个处理器来解析这个注解。

    • 实现了 SmartInitializingSingleton。
  • 把监听器加入到容器。

  • 只要容器中有相关事件的发布,我们就能监听到这个事件。

    ContextRefreshedEvent:容器刷新完成(所有 Bean 都创建完成)会发布这个事件。

    ContextCloseEvent:关闭容器会发布这个事件。

  • 发布一个事件:applicationContext.pushlishEvent。

原理:

ContextRefreshEvent 事件

  • 容器创建对象:refresh()

  • finishRefresh(),容器刷新完成

  • publishEvent(new ContextRefreshedEvent(this))

    【发布流程】

    • 获取事件多播器(派发器):getApplicaitonEvnetMulticaster()

    • multicastEvent 派发事件

    • 获取到所有的 ApplicationListener

      如果 Listener 里有 Executor,可以支持使用 Executor 进行异步派发。

      Executor executor = getTaskExecutor();
      

      否则同步的方式直接执行 listener 方法,里面通过 listener 回调 onApplicationEvent(envet) 方法。

      invokeListener(listener, event);
      

SmartInitializingSingleton

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

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

过程:

  • IOC 容器创建对象并 refresh 容器
  • finishBeanFactoryInitialization(beanFactory),初始化剩下的单实例 Bean。
    • 创建所有的单实例 Bean,for 循环 + getBean() .
    • 获取创建好的单实例 Bean,判断是否是 SmartInitializingSingleton,如果是就调用 afterSingletonsInstantiated 方法。

相关文章

网友评论

      本文标题:Spring 源码解析(一)

      本文链接:https://www.haomeiwen.com/subject/qtfxfctx.html