一、BeanFactoryPostProcessor

  BeanFactory的后置处理器:在BeanFactory标准初始化之后调用,来定制和修改BeanFactory的内容;所有的bean定义已经保存加载到beanFactory,但是bean的实例还未创建

1,使用

  源码:MyBeanFactoryPostProcess

@Component
public class Demo01_MyBeanFactoryPostProcess implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("MyBeanFactoryPostProcessor...postProcessBeanFactory...");
int definitionCount = beanFactory.getBeanDefinitionCount();
String[] definitionNames = beanFactory.getBeanDefinitionNames();
System.out.println("beanFactory中一共有 " + definitionCount + " 个bean,分别为: " + Arrays.toString(definitionNames));
}
}

2,BeanFactoryPostProcessor原理

  • 1)、ioc容器创建对象
  • 2)、invokeBeanFactoryPostProcessors(beanFactory);
    • 先根据类型获取各种postProcessorNames。String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    • 分类保存为各种priorityOrderedPostProcessors、orderedPostProcessors、nonOrderedPostProcessors的集合其实就是各种BeanFactoryPostProcessor
    • 然后分别排序上一步的各种集合,按顺序分别执行各种BeanFactory的后置处理器

二、BeanDefinitionRegistryPostProcessor

  • 在所有bean定义信息将要被加载,bean实例还未创建的;
  • 优先于BeanFactoryPostProcessor执行
  • 利用BeanDefinitionRegistryPostProcessor给容器中再额外添加一些组件;

1,使用

  源码:MyBeanDefinitionRegistryPostProcessor

@Component
public class Demo02_MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
/**
* @param registry Bean定义信息的保存中心,以后BeanFactory就是按照BeanDefinitionRegistry里面
* 保存的每一个bean定义信息创建bean实例;
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("postProcessBeanDefinitionRegistry...bean的数量:"+registry.getBeanDefinitionCount());
RootBeanDefinition definition = new RootBeanDefinition(Dog.class);
registry.registerBeanDefinition("dog",definition);
} @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("MyBeanDefinitionRegistryPostProcessor...bean的数量:"+beanFactory.getBeanDefinitionCount());
}
}

2,BeanDefinitionRegistryPostProcessor原理

  • 1)、ioc创建对象
  • 2)、refresh() -> invokeBeanFactoryPostProcessors(beanFactory);
  • 3)、从容器中获取到所有的BeanDefinitionRegistryPostProcessor组件。String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class ..);
    • invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry) -> 依次触发所有的postProcessBeanDefinitionRegistry()方法
    • 再来触发invokeBeanFactoryPostProcessors(registryProcessors, beanFactory) -> postProcessBeanFactory()方法BeanFactoryPostProcessor;
  • 4)、之后从容器中找到BeanFactoryPostProcessor组件;然后依次触发postProcessBeanFactory()方法(也就是第一章内容)

三、监听器

1,ApplicationEvent

a)使用

  源码:MyApplicationEvent

@Component
public class Demo4_ApplicationEvent implements ApplicationListener {
//监听所有ApplicationEvent以及其子类发布的事件
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("ApplicaitonEvent ====> " + event);
}
}

b)原理

  • 1)、ContextRefreshedEvent事件:

    • 容器创建对象:refresh();
    • finishRefresh();容器刷新完成会发布ContextRefreshedEvent事件
  • 2)、自己发布事件;
  • 3)、容器关闭会发布ContextClosedEvent;

【事件发布流程】
  publishEvent(new ContextRefreshedEvent(this));

  • 获取事件的多播器(派发器):getApplicationEventMulticaster()
  • multicastEvent派发事件:
  • 获取到所有的ApplicationListener

   for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {..}

    • 如果有Executor,可以支持使用Executor进行异步派发;Executor executor = getTaskExecutor();
    • 否则,同步的方式直接执行listener方法;invokeListener(listener, event);
      拿到listener回调onApplicationEvent方法;

【事件多播器(派发器)】

  • 1)、容器创建对象:refresh();
  • 2)、initApplicationEventMulticaster();初始化ApplicationEventMulticaster;
    • 先去容器中找有没有id=“applicationEventMulticaster”的组件;
    • 如果没有this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);并且加入到容器中,我们就可以在其他组件要派发事件,自动注入这个applicationEventMulticaster;

【容器中有哪些监听器】

  • 1)、容器创建对象:refresh();
  • 2)、registerListeners();
    • 从容器中拿到所有的监听器,把他们注册到applicationEventMulticaster中;
    • String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    • //将listener注册到ApplicationEventMulticaster中 getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);

2,@EventListener

a)使用

  源码:MyListener

/**
* 普通方法加注解就可以监听任意指定的Class
*/
@EventListener(classes = {Cat.class})
public void listener(Cat cat){
System.out.println(cat);
}

b)原理

  @EventListener -> EventListenerMethodProcessor -> SmartInitializingSingleton

  SmartInitializingSingleton 原理:->afterSingletonsInstantiated();

  • 1)、ioc容器创建对象并refresh();
  • 2)、finishBeanFactoryInitialization(beanFactory);初始化剩下的单实例bean;
    • 1)、先创建所有的单实例bean;getBean();
    • 2)、获取所有创建好的单实例bean,判断是否是SmartInitializingSingleton类型的;如果是就调用afterSingletonsInstantiated();

四、Spring容器的创建原理

1,创建方式

//创建基于注解的springIOC容器
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
//创建基于配置文件的springIOC容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-app.xml");

2,执行AbstractApplicationContext中的refresh()

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. Prepare this context for refreshing.
prepareRefresh(); // 2. Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 3. Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory); try {
// 4. Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory); // 5. Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory); // 6. Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory); // 7. Initialize message source for this context.
initMessageSource(); // 8. Initialize event multicaster for this context.
initApplicationEventMulticaster(); // 9. Initialize other special beans in specific context subclasses.
onRefresh(); // 10. Check for listener beans and register them.
registerListeners(); // 11. Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory); // 12. Last step: publish corresponding event.
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
} // Destroy already created singletons to avoid dangling resources.
destroyBeans(); // Reset 'active' flag.
cancelRefresh(ex); // Propagate exception to caller.
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}

3,源码解析

1. prepareRefresh 准备刷新容器

  (1) initPropertySources() 自定义属性设置,空方法,留给子类继承

  (2) getEnvironment.validateRequiredProperties 首先获取环境配置,然后校验必需属性

  (3) this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); 初始化事件监听器

  (4) this.earlyApplicationEvents = new LinkedHashSet<>();  初始化早期事件

2. obtainFreshBeanFactory 获取组件工厂

  (1) refreshBeanFactory  新建一个组件工厂,类型为DefaultListableBeanFactory,然后对这个组件工厂设置了一个序列化ID

  (2) getBeanFactory 返回刚刚创建的组件工厂

3. prepareBeanFactory 对组件工厂做各种预处理设置

  (1) 在组件工厂中设置类加载器、属性解析器等

  (2) 在组件工厂中添加部分组件后置处理器,例如ApplicationContextAwareProcessor、ApplicationListenerDetector

  (3) 在组件工厂中设置忽略自动注入的接口

  (4) 设置自动装配规则

  (5) 在组件工厂中注册一些组件,例如环境配置ConfigurableEnvironment

4. postProcessBeanFactory 组件工厂的后置处理工作

5. invokeBeanFactoryPostProcessors 执行组件工厂后置处理器

  这一步是在组件工厂的标准初始化(1-4)之后进行的,主要是执行BeanFactoryPostProcessor及其子接口的

  BeanFactoryPostProcessor的子接口主要是指BeanDefinitionRegistryPostProcessor,可以向容器中注册新的组件,这个接口的特点是有两个方法,一个是自身的postProcessBeanDefinitionRegistry,另一个继承自BeanFactoryPostProcessor的postProcessBeanFactory,从源码可以看出,spring会先执行BeanDefinitionRegistryPostProcessor类型的组件的自身方法,然后执行其继承方法,最后才调用非BeanDefinitionRegistryPostProcessor的BeanFactoryPostProcessor的后置处理方法

  (1) 从容器器中获取BeanDefinitionRegistryPostProcessor类型的组件

  (2) 将BeanDefinitionRegistryPostProcessor类型的组件按照顺序分类并排序,即是否实现了PriorityOrdered、Ordered接口

  (3) 依次执行实现了PriorityOrdered接口的、实现了Ordered接口的、没有实现任何顺序接口的组件的postProcessBeanDefinitionRegistry方法

  (4) 执行所有BeanDefinitionRegistryPostProcessor组件的postProcessBeanFactory方法

  (5) 从容器中获取其他的BeanFactoryPostProcessor类型的组件,即不是BeanDefinitionRegistryPostProcessor类型的

  (6) 剩下的步骤跟上面类似,就是先按照实现的顺序接口分类,在每个类别下排序,然后依次执行它们的postProcessBeanFactory方法

6. registerBeanPostProcessors 注册组件后置处理器,

  这种处理器用于拦截bean的创建过程。beanPostProcessor有很多子接口,每种子接口的执行时机各有不同

  |-DestructionAwareBeanPostProcessor

  |-InstantiationAwareBeanPostProcessor  

  |-MergedBeanDefinitionPostProcessor

  |-SmartInstantiationAwareBeanPostProcessor

  (1) 获取所有的beanPostProcessor的组件名

  (2) 将所有的组件按优先顺序分为三类:

     |-实现了PriorityOrdered接口的列表priorityOrderedPostProcessors

     |-实现了Ordered接口的列表orderedPostProcessors

     |-没有实现任何顺序接口的列表nonOrderedPostProcessors

      还有一种特殊情况,凡是MergedBeanDefinitionPostProcessor类型的,都放在internalPostProcessors中

  (3) 注册priorityOrderedPostProcessors

  (4) 注册orderedPostProcessors

  (5) 注册nonOrderedPostProcessors

  (6) 注册internalPostProcessors

  (7) 注册ApplicationListenerDetector,它的作用是在组件初始化之后判断其是否为ApplicationListner类型,如果是,则将其添加进容器的监听器集合。

7. initMessageSource 初始化消息源组件

  用于消息绑定、消息解析等功能,并且提供国际化解决方案

  (1) 获取beanFactory

  (2) 判断beanFactory中是否包含id为messageSource的组件

  (3) 如果已存在,则赋值给容器的messageSource属性,这种情况是我们自己在容器中注册了这个组件

  (4) 如果不存在,则新建一个DelegatingMessageSource,并赋值给容器的messageSource属性,然后在beanFactory中注册这个新组件,并设置其id为messageSource

8. initApplicationEventMulticaster 初始化事件广播器

  (1) 获取beanFactory

  (2) 判断beanFactory中是否存在id为applicationEventMulticaster的组件

  (3) 如果已存在,则赋值给容器的applicationEventMulticaster属性,这种情况是我们自己在容器中注册了这个组件

  (4) 如果不存在,则新建一个SimpleApplicationEventMulticaster,并赋值给容器的 applicationEventMulticaster属性,然后在beanFactory中注册这个新组件, 并设置其id为applicationEventMulticaster。

9. onRefresh

  留给子类继承的,我们可以自定义子容器,在重写方法中做一些我们想要的操作

10. registerListeners 注册事件监听器

  (1) 获取容器的属性applicationListeners,这是一个事件监听器的集合,将集合中的每个元素都添加进事件广播器getApplicationEventMulticaster().addApplicationListener(listener);

  (2) 从容器中获取所有ApplicationListener类型的组件,将这些组件添加进事件广播器

  (3) 派发之前步骤产生的事件。

11. finishBeanFactoryInitialization 完成剩下的单实例bean的初始化

  (1) 进入DefaultListableBeanFactory.preInstantiateSingletons方法,获取容器中所有的组件id列表
  (2) 获取容器中的所有Bean,依次进行初始化和创建对象
  (3) Bean不是抽象的,是单实例的,是非懒加载
    1)、判断是否是FactoryBean;是否是实现FactoryBean接口的Bean;如果是就用工厂bean来创建及FacBean中的getObject同SpringIOC中的二(3)
    2)、不是工厂Bean。利用getBean(beanName);创建对象
      0、getBean(beanName); ioc.getBean();
      1、AbstractBeanFactory.doGetBean(name, null, null, false);
      2、先获取缓存中保存的单实例Bean。如果能获取到说明这个Bean之前被创建过(所有创建过的单实例Bean都会被缓存起来),Object sharedInstance = getSingleton(beanName);缓存到DefaultSingletonBeanRegistry类的singletonObjects单例对象存储的Map一级缓存。
      3、缓存中获取不到,开始Bean的创建对象流程;
      4、标记当前bean已经被创建,markBeanAsCreated(beanName);
      5、获取Bean的定义信息;RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName)
      6、【获取当前Bean依赖的其他Bean;如果有按照getBean(dep)把依赖的Bean先创建出来;】String[] dependsOn = mbd.getDependsOn()
      7、启动单实例Bean的创建流程
        1)AbstractAutowireCapableBeanFactory.createBean(beanName, mbd, args);

        2)Object bean = resolveBeforeInstantiation(beanName, mbdToUse);让BeanPostProcessor先拦截返回代理对象;【InstantiationAwareBeanPostProcessor】:提前执行;先触发:postProcessBeforeInstantiation();如果有返回值:触发postProcessAfterInitialization();
        3)如果前面的InstantiationAwareBeanPostProcessor没有返回代理对象;调用AbstractAutowireCapableBeanFactory.doCreateBean创建Bean

          1. 【创建Bean实例】;createBeanInstance(beanName, mbd, args);利用工厂方法或者对象的构造器创建出Bean实例;
          2.  applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);调用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition(mbd, beanType, beanName);
          3. 【Bean属性赋值】populateBean(beanName, mbd, instanceWrapper);
            ① 拿到InstantiationAwareBeanPostProcessor后置处理器;postProcessAfterInstantiation();
            ② 拿到InstantiationAwareBeanPostProcessor后置处理器;postProcessPropertyValues();
            ③ 为Bean属性赋值;为属性利用setter方法等进行赋值;applyPropertyValues(beanName, mbd, bw, pvs);
          4.【Bean初始化】initializeBean(beanName, exposedObject, mbd);
            1. 【执行Aware接口方法】invokeAwareMethods(beanName, bean);执行xxxAware接口的方法BeanNameAware\BeanClassLoaderAware\BeanFactoryAware
            2. 【执行后置处理器初始化之前】applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);BeanPostProcessor.postProcessBeforeInitialization();
            3. 【执行初始化方法】invokeInitMethods(beanName, wrappedBean, mbd);
              ① 是否是InitializingBean接口的实现;执行接口规定的初始化;
              ② 是否自定义初始化方法;
            4. 【执行后置处理器初始化之后】applyBeanPostProcessorsAfterInitialization 也就是BeanPostProcessor.postProcessAfterInitialization();
          5. 注册Bean的销毁方法;registerDisposableBeanIfNecessary(beanName, bean, mbd);

        4)将创建的Bean添加到缓存中singletonObjects

12. finishRefresh 完成容器刷新

  (1) 初始化生命周期处理器(LifecycleProcessor),先从BeanFactory中按类型获取,如果没有就新建一个DefaultLifecycleProcessor,并注册进BeanFactory

  (2) 获取上一步注册的生命周期处理器,回调其onRefresh方法

  (3) 发布容器刷新事件,即ContextRefreshedEvent

4,总结

  1)、Spring容器在启动的时候,先会保存所有注册进来的Bean的定义信息;
    1、xml注册bean;<bean>
    2、注解注册Bean;@Service、@Component、@Bean、xxx
  2)、Spring容器会合适的时机创建这些Bean
    1、用到这个bean的时候;利用getBean创建bean;创建好以后保存在容器中;
    2、统一创建剩下所有的bean的时候;finishBeanFactoryInitialization();
  3)、后置处理器;BeanPostProcessor
    每一个bean创建完成,都会使用各种后置处理器进行处理;来增强bean的功能;
    AutowiredAnnotationBeanPostProcessor:处理自动注入
    AnnotationAwareAspectJAutoProxyCreator:来做AOP功能;
    ....
    增强的功能注解:
    AsyncAnnotationBeanPostProcessor
    ....
  4)、事件驱动模型
    ApplicationListener;事件监听;
    ApplicationEventMulticaster;事件派发:

Spring中各种扩展原理及容器创建原理的更多相关文章

  1. 使用反射创建Bean、Spring中是如何根据类名配置创建Bean实例、Java提供了Class类获取类别的字段和方法,包括构造方法

    Java提供了Class类,可以通过编程方式获取类别的字段和方法,包括构造方法    获取Class类实例的方法:   类名.class   实例名.getClass()   Class.forNam ...

  2. Spring源码学习之IOC容器实现原理(一)-DefaultListableBeanFactory

    从这个继承体系结构图来看,我们可以发现DefaultListableBeanFactory是第一个非抽象类,非接口类.实际IOC容器.所以这篇博客以DefaultListableBeanFactory ...

  3. Spring中异步注解@Async的使用、原理及使用时可能导致的问题

    前言 其实最近都在研究事务相关的内容,之所以写这么一篇文章是因为前面写了一篇关于循环依赖的文章: <面试必杀技,讲一讲Spring中的循环依赖> 然后,很多同学碰到了下面这个问题,添加了S ...

  4. springboot(八) 嵌入式Servlet容器自动配置原理和容器启动原理

    1.嵌入式Servlet容器自动配置原理 1.1 在spring-boot-autoconfigure-1.5.9.RELEASE.jar => springboot自动配置依赖 jar包下,E ...

  5. 阶段3 2.Spring_03.Spring的 IOC 和 DI_6 spring中bean的细节之三种创建Bean对象的方式

    目前这里能调用是因为,在service的实现类里面,new了一个dao的对象 正常情况下 这里不应该是new一个对象,应该等于null或为空 设置为空侯再运行就会报错 出错的原因是这里为null 需要 ...

  6. Spring 中如何自动创建代理(spring中的三种自动代理创建器)

    Spring 提供了自动代理机制,可以让容器自动生成代理,从而把开发人员从繁琐的配置中解脱出来 . 具体是使用 BeanPostProcessor 来实现这项功能. 这三种自动代理创建器 为:Bean ...

  7. Spring中FactoryBean的作用和实现原理

    BeanFactory与FactoryBean,相信很多刚翻看Spring源码的同学跟我一样很好奇这俩货怎么长得这么像,分别都是干啥用的.BeanFactory是Spring中Bean工厂的顶层接口, ...

  8. Spring 中的反射与反射的原理

    作者:DeppWang.原文地址 在造轮子:实现一个简易的 Spring IoC 容器一文中提到 Spring 在创建 Bean 实例和依赖注入时使用了反射,本文来具体分析一下 Spring 中的反射 ...

  9. 通过BeanPostProcessor理解Spring中Bean的生命周期

    通过BeanPostProcessor理解Spring中Bean的生命周期及AOP原理 Spring源码解析(十一)Spring扩展接口InstantiationAwareBeanPostProces ...

随机推荐

  1. C# 静态类 单例模式 对比

    公司的类都需要使用单例模式实现,这个可以节省资源,避免重复对象的生成.但是静态类也可以做到这一点,而且写起来更简洁,于是查阅相关资料,希望弄明白两者的差别. 1.单例模式可以在用到的时候初始化,而静态 ...

  2. 要想用活Redis,Lua脚本是绕不过去的坎

    前言 Redis 当中提供了许多重要的高级特性,比如发布与订阅,Lua 脚本等.Redis 当中也提供了自增的原子命令,但是假如我们需要同时执行好几个命令的同时又想让这些命令保持原子性,该怎么办呢?这 ...

  3. 在kubernetes集群里集成Apollo配置中心(5)之dubbo服务消费者连接apollo实战

    1.在Apollo的portal创建dubbo消费者项目 (1)添加dubbo消费者项目 (2)在dubbo消费者项目中添加配置项 (3)发布 2.通过jenkins构建dubbo消费者镜像 3.登录 ...

  4. Leetcode(35)-搜索插入位置

    给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引.如果目标值不存在于数组中,返回它将会被按顺序插入的位置. 你可以假设数组中无重复元素. 这个题目很简单,因为它是给定的排序数组而且没有重 ...

  5. 2017.8.11 think list

    递推式与模数不互质,如何利用中国剩余定理综合答案

  6. Web 安全漏洞 All In One

    Web 安全漏洞 All In One Web 安全 & 漏洞 输入输出验证不充分 SQL 注入 XSS self-XSS CSRF 目录穿越 文件上传 代码注入 命令注入 信息漏洞 暴力破解 ...

  7. GitHub in depth

    GitHub in depth GitHub 高级玩法 / 进阶教程 https://github.com/trending/dart?since=daily https://github.com/t ...

  8. Beacon API All In One

    Beacon API All In One Beacon API https://developer.mozilla.org/en-US/docs/Web/API/Beacon_API https:/ ...

  9. Redis all in one

    Redis all in one Redis: REmote DIctionary Server https://redis.io/topics/quickstart Download, extrac ...

  10. HTTP/1.1 & HTTP/2 & webpack

    HTTP/1.1 & HTTP/2 & webpack Bundling your application is especially powerful for HTTP/1.1 cl ...