zoukankan      html  css  js  c++  java
  • spring-boot源码分析之BeanFactory

    前言

    今天原本是打算分析beanFactory的,但由于昨天我们有一部分内容还没有分享完,所以今天就先开个倒车,把做昨天的内容先将清楚,所以今天的内容主要就是对昨天分享内容的的补充。

    当然,昨天我们分享的内容beanDefinitionNames也算是BeanFactory的核心属性,所以也不能说完全没有关系:

    而且从源码中我们可以看出来,beanDefinitionNamesbeanDefinitionMap这些属性的初始化大小,这也算是在学习beanFactory的相关知识吧。

    BeanFactory

    beanDefinitionNames内容补充

    正式开始之前,我们先把昨天遗留的问题解决了。昨天,我们分享了一张beanDefinitionNames初始化的时序图,但是由于有一些内容没有梳理清楚,所以这里先做个补充。

    调用过程各方法作用

    SpringApplication这里就不做过多说明了,我们在前面最开始的时候就已经分析过这个类的run方法,当时也已经介绍过这个类的这些方法,他们的主要作用就是为了初始化容器,在SpringApplication的最后一个refresh方法中,最后会调用AbstractApplicationContext自身的refresh方法,这里的AbstractApplicationContextApplicationContext的抽象实现,它实现了ConfigurableApplicationContext接口(ConfigurableApplicationContext继承了ApplicationContext),我们的AnnotationConfigReactiveWebServerApplicationContext(默认容器)就是继承自它,不过并不是直接继承,它的父类继承了AbstractApplicationContext,关于容器这块的继承关系,我们改天抽个时间,专门分析下。

    大部分继承了AbstractApplicationContext的容器都没有重写refresh方法,就算重写了这个方法,其内部也是调用了父类的refresh方法:

    我们看下refresh的实现源码:

    	public void refresh() throws BeansException, IllegalStateException {
    		synchronized (this.startupShutdownMonitor) {
    			// Prepare this context for refreshing.
    			prepareRefresh();
    
    			// Tell the subclass to refresh the internal bean factory.
    			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
    			// Prepare the bean factory for use in this context.
    			prepareBeanFactory(beanFactory);
    
    			try {
    				// Allows post-processing of the bean factory in context subclasses.
    				postProcessBeanFactory(beanFactory);
    
    				// Invoke factory processors registered as beans in the context.
    				invokeBeanFactoryPostProcessors(beanFactory);
    
    				// Register bean processors that intercept bean creation.
    				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();
    			}
    
    			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();
    			}
    		}
    	}
    

    refresh方法内部,调用了很多其他方法,其中prepareRefresh的作用是为我们下面的刷新操作做准备,其内部主要是对配置的一些初始化操作:

    obtainFreshBeanFactory方法的作用是刷新beanFactory,主要是对beanFactory进行一些初始化操作,如果beanFactory已经存在,会将已有的beanFactory销毁,然后重新创建,最后将beanFactory返回:

    prepareBeanFactory方法的作用是对BeanFactory进行一些赋值和设置,为容器初始化操作做准备:

    postProcessBeanFactory方法就是我们昨天提到的会进行包扫描的那个方法,但由于basePackagesannotatedClasses都是空,所以其中的scan方法并不会被执行。这个方法实际的作用是,后置处理BeanFactory

    invokeBeanFactoryPostProcessors方法的作用是,实例化并调用所有注册的BeanFactory的后置处理器。我们昨天说的beanDefinitionNamesbeanDefinitionMap就是通过这个方法最终完成初始化的:

    registerBeanPostProcessors方法和它名字一样,它的作用就是注册bean的后置处理器:

    initMessageSource方法是进行消息源初始化的,主要是对web应用消息国际化提供支持的:

    initApplicationEventMulticaster,这个方法是初始化spring boot应用时间广播的,如果不指定的话,默认情况下为我们指定的是SimpleApplicationEventMulticaster

    onRefresh,这个方法是提供给子类初始化其他特殊bean对象的,默认实现为空,子类可根据需要重写:

    registerListeners方法是用来注册事件监听器的:

    finishBeanFactoryInitialization,完成beanFactory初始化,同时在方法内部会实例化剩余的单例类(不包括懒加载部分):

    finishRefresh,完成刷新,主要进行一些清理、刷新、事件推送等操作:

    总结

    经过今天的补充之后,我相信各位小伙伴一定也对spring boot的启动和初始化过程有了更深刻的认识,因为我就是这样的感受。相比于昨天分享完内容的感受,今天我感觉整体来说要更好。一方面感觉spring boot启动和初始化的流程更清晰了,而且由于最近这几天一直在看spring boot的源码,看的多了感觉就没有那么难了,毕竟书读百遍其意自现,代码也是大同小异;另一方面在梳理分析的过程中,让我也能够清晰地看到下一步要分享的内容,明确后面地前进方向,这也算是意外的收获吧。

  • 相关阅读:
    TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常?
    当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?
    @Qualifier 注解?
    Set里的元素是不能重复的,那么用什么方法来区分重复与否呢?是用==还是equals()?它们有何区别?
    Filter是什么?有什么作用?
    List和 Map区别?
    Spring框架的事务管理有哪些优点?
    Listener是什么?有什么作用?
    字节流与字符流的区别?
    Struts2里面有什么隐式对象?
  • 原文地址:https://www.cnblogs.com/caoleiCoding/p/15232227.html
Copyright © 2011-2022 走看看