深入理解 Spring BeanFactoryPostProcessor的回调(一)

简介: 深入理解 Spring BeanFactoryPostProcessor的回调(一)

程序入口:#


接着上一篇博客中看完了在AnnotationConfigApplicationContext的构造函数中的register(annotatedClasses);将我们传递进来的主配置类添加进了BeanFactory, 本片博客继续跟进refresh(); 看看Spring如何继续初始化Spring的环境


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


跟进refresh(), 源码如下: 主要做了如下几件工作

  • 刷新的预准备
  • 比如: 设置时间的锚点,加载上下文环境变量
  • 获取BeanFactory
  • 执行所有的BeanFactoryPostProcessor
  • 执行所有的BeanPostProcessor
  • ...


public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
  // Prepare this context for refreshing.
  //准备刷新
  prepareRefresh();
    //获取BeanFactory 
  ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    // 准备BeanFactory
  prepareBeanFactory(beanFactory);
  try {
    // 方法中没有任何实现的逻辑
    postProcessBeanFactory(beanFactory);
    // invoke BeanFactoryPostprocessor, 执行bean工厂的后置处理器
    //如果我们没有手动往Spring中注入bean工厂的后置处理器,那么此时仅有一个,也是beanFactoryMap中的第一个RootBeanDefinition-> ConfigurationClassPostProcessor
    invokeBeanFactoryPostProcessors(beanFactory);
    // 注册 bean的后置处理器, 这些处理器可以在bean的构造方法执行之后再执行init()方法前后执行指定的逻辑
    registerBeanPostProcessors(beanFactory);
    // Initialize message source for this context.
    initMessageSource();
    // Initialize event multicaster for this context.
    initApplicationEventMulticaster();
    // Initialize other special beans in specific context subclasses.
    onRefresh();
    // Check for listener beans and register them.
    registerListeners();
    // Instantiate all remaining (non-lazy-init) singletons.
    finishBeanFactoryInitialization(beanFactory);
    // Last step: publish corresponding event.
    finishRefresh();
  }
  }
}


刷新的准备工作#


这个方法没啥可看的重要逻辑,记录了下开始的时间,然后为Spring的上下文加载可用的环境变量


protected void prepareRefresh() {
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);
    if (logger.isInfoEnabled()) {
      logger.info("Refreshing " + this);
    }
    //  这个是protected类型的方法,目前还没有任何实现
    initPropertySources();
    //   校验所有需要的properties是否都被解析过了
    //   getEnvironment() 得到系统环境, 后续的@Profile使用
    getEnvironment().validateRequiredProperties();
    this.earlyApplicationEvents = new LinkedHashSet<>();
  }


获取BeanFactory#


获取出BeanFactory,接下来的工作重点是去扫描出程序员提供的类,然后将它们放进BeanFactoryMap中,在此过程中穿插执行BeanFactoryPostProcessorBeanPostPorcessor, 不难看出后续工作的进展都离不开这个BeanFactoryMap,这个map在哪里呢? 就在我们的beanFactory中,因此在刷新的最开始,获取出bean工厂



当前类是AbstractApplicationContext,上图是它的继承类图,通过上图可以看到,它是入口AnnotationConfigApplicationContext

GenericApplicationContext的父类,而Spring的BeanFactory是在GenericApplicationContext中实例化的,故, 获取beanFactory的逻辑肯定在当前方法中被设计成抽象的方法,而由自己具体实现,源码如下:


@Override
  public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;


准备beanFactory#


上面的逻辑是获取出BeanFactory, 那什么是准备BeanFactory呢? 看它的注解解释是: 为BeanFactory配置上它应该具有的所有特征, 那BeanFactory应该有什么特征呢? 类加载器 , bean表达式的解析器 , property与对象的转换器 , bean的后置处理器 , 添加禁止用户注入的bean的信息 , 注入bean的替换 , 添加默认的和环境相关的bean

源码如下:它的解析我们写在下面


protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
  // 添加类加载器
  beanFactory.setBeanClassLoader(getClassLoader());
  // 设置bean标签的解析器, 一般我们使用spel标签比较多,但是Spring也有自己的Bean标签 
  beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
  // </property ref="XXX"> 解析转换xxx 替换成对象
  beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
  // 添加bean的后置处理器,很显然这里添加的是Spring自己的后置处理器
  beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
  // 当用户企图注入下面类型的对象时, 会被Spring忽略
  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.class , 那Spring会将她替换成beanFactory
  beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
  beanFactory.registerResolvableDependency(ResourceLoader.class, this);
  beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
  beanFactory.registerResolvableDependency(ApplicationContext.class, this);
  // Register early post-processor for detecting inner beans as ApplicationListeners.
  beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
  // Detect a LoadTimeWeaver and prepare for weaving, if found.
  if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
    beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
    // Set a temporary ClassLoader for type matching.
    beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
  }
  // 意思是如果自定义的Bean中没有名为"systemProperties"和"systemEnvironment"的Bean,
  // 则注册两个Bena,Key为"systemProperties"和"systemEnvironment",Value为Map,
  // 这两个Bean就是一些系统配置和系统环境信息
  //  注册默认的和环境相关的 bean   Sping会检测,我们自己注册进来的Bean中有没有下面的名字叫下面三个串的对象, 没有的话就帮我们注入进来
  if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { //   environment_bean_name
    beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
  }
  if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {//   system_properties_bean_name
    beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
  }
  if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {//   system_environment_bean_name
    beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
  }
}


如上代码的作用就是为BeanFactory初始化了Spring规定的几个必须的配置属性,其中比较值得注意的地方就是它添加的BeanPostProcessor, 虽然这是Spring原生的bean的后置处理器,但是也是第一次出现,很有意义,配置expressContext等工作, 这个后置处理器会在Bean的构造的构造过程中,动态的拦截插手


此外,添加了忽略注入的对象,当程序员向注入Spring启动时,依赖的原生对象时,会被忽略注入,企图注入BeanFactory,资源解析器,事件发布器,应用上下文时,被Spring使用原生的对象替换掉




相关文章
|
Java Spring 容器
深入理解Spring源码之IOC 扩展原理BeanFactoryPostProcessor和事件监听ApplicationListener
深入理解Spring源码之IOC 扩展原理BeanFactoryPostProcessor和事件监听ApplicationListener
|
XML Java 数据格式
Spring高手之路13——BeanFactoryPostProcessor与BeanDefinitionRegistryPostProcessor解析
在Spring框架中,BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor是两个重要的后置处理器,它们在容器的启动过程中起到了至关重要的作用。本文深入探讨了这两者的定义、功能、执行时机以及如何在实际项目中使用它们。同时,通过对比分析,为读者揭示了它们与其他后置处理器之间的差异。无论你是初学者还是有一定经验的开发者,都能从中获得深入的理解和启示。
341 2
Spring高手之路13——BeanFactoryPostProcessor与BeanDefinitionRegistryPostProcessor解析
|
XML 开发框架 Java
聊聊Spring扩展点BeanPostProcessor和BeanFactoryPostProcessor
今天聊一聊spring中很重要的两个扩展点BeanPostProcessor和BeanFactoryPostProcessor,spring之所以如次强大,是因为它提供了丰富的功能给我们使用,但是我觉得最强大的是它扩展点,因为有了各种扩展点,我们才能去开发一些自己的需求,一个框架的强大之处也在于它能否灵活的配置,能够支持很好的扩展。
66 0
|
XML Java 数据库连接
深入理解Spring IOC之扩展篇(二)、BeanFactoryPostProcessor和BeanPostProcessor
深入理解Spring IOC之扩展篇(二)、BeanFactoryPostProcessor和BeanPostProcessor
95 1
|
Java Spring 容器
Spring - BeanFactoryPostProcessor 扩展接口
BeanFactoryPostProcessor 扩展接口
121 0
Spring - BeanFactoryPostProcessor 扩展接口
|
Java Spring 容器
一文吃透Spring Boot扩展之BeanFactoryPostProcessor
一文吃透Spring Boot扩展之BeanFactoryPostProcessor
170 0
一文吃透Spring Boot扩展之BeanFactoryPostProcessor
|
Java 数据库连接 Spring
Spring源码分析之BeanFactoryPostProcessor调用过程(二)
Spring源码分析之BeanFactoryPostProcessor调用过程
112 0
|
Java 数据库连接 Spring
Spring源码分析之BeanFactoryPostProcessor调用过程(一)
Spring源码分析之BeanFactoryPostProcessor调用过程
109 0
|
JavaScript Java 数据库连接
spring对hibernate的集成中的回调(CallBack)机制
spring对hibernate的集成中的回调(CallBack)机制
218 0
spring对hibernate的集成中的回调(CallBack)机制
|
Java 数据库连接 uml
Spring官网阅读(六)容器的扩展点(一)BeanFactoryPostProcessor
Spring官网阅读(六)容器的扩展点(一)BeanFactoryPostProcessor
80 0
Spring官网阅读(六)容器的扩展点(一)BeanFactoryPostProcessor