Spring IOC容器初始化主体流程

Spring IOC容器初始化主体流程

Spring IOC的容器体系

IOC容器时Spring的核心模块,是抽象了对象管理、依赖关系管理的框架解决方案。

Spring 提供了很多的容器,其中BeanFactory是顶层容器(根容器),不能被实例化,它定义了所有的IOC容器必须遵从的一套原则,具体的容器实现可以增加额外的功能。

比如我们常用到的ApplicationContext,其下更具体的实现如 ClassPathXMLApplicationContext包含了解析xml等一系列的内容。

AnnotationConfigApplicationContext则是包含了注解解析等一系列的内容。Spring IOC容器继承体系设计得非常游侠,需要使用哪个接口实现哪个接口即可,不必实现一个功能复杂的大接口。

BeanFactory顶级接口的方法如下:
在这里插入图片描述
BeanFactory 容器继承体系:
在这里插入图片描述
通过其接口设计,我们可以看到我们一贯使用的ApplicationContext除了继承BeanFactory的子接口,还继承了ResourceLoader、MessageSource等接口,因此其提供的功能也就更丰富了。

下面我们以ClassPathXmlApplicationContext 为例,深入源码说明IOC容器的初始化流程

Bean生命周期关键时机点

思路:创建一个MyBean,让其实现几个特殊的接口,并分别在接口实现的构造器、接口方法中断点,观察线程调用栈,分析出Bean对象创建和管理关键点的触发时机

MyBean类:

public class MyBean implements InitializingBean {

	private int id;

	private String name;

	public MyBean() {
		System.out.println("构造器执行了......");
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("afterPropertiesSet执行了......");
	}
}

MyBeanFactoryPostProcessor 后置处理器工厂实现类:

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

	public MyBeanFactoryPostProcessor(){
		System.out.println("MyBeanFactoryPostProcessor的构造函数......");
	}

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("MyBeanFactoryPostProcessor的实现方法调用了......");
	}
}

MyBeanPostProcessor 后置处理器实现类:

public class MyBeanPostProcessor implements BeanPostProcessor {

	public MyBeanPostProcessor() {
		System.out.println("MyBeanPostProcessor构造方法调用了......");
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if("myBean".equals(beanName)){
			System.out.println("MyBeanPostProcessor的before方法调用了......");
		}
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if("myBean".equals(beanName)){
			System.out.println("MyBeanPostProcessor的after方法调用了......");
		}
		return bean;
	}
}

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<bean id="myBean" class="com.myspring.demo.MyBean">
	</bean>

	<bean id="myBeanPostProcessor" class="com.myspring.demo.MyBeanPostProcessor"/>
	<bean id="myBeanFactoryPostProcessor" class="com.myspring.demo.MyBeanFactoryPostProcessor"/>
	
</beans>

测试代码:

public class MyTest {

	@Test
	public void	MySpringTest(){
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
		MyBean myBean = (MyBean) applicationContext.getBean("myBean");
		System.out.println(myBean);
	}
}

我们在MyTestMyBean myBean = (MyBean) applicationContext.getBean("myBean"); 这行代码打断点:

  • 分析Bean的创建是在容器初始化还是在getBean时:
    在这里插入图片描述

  • 根据断点调试,我们发现,在未设置延迟加载的前提下,Bean的创建是在容器初始化过程中完成的

  • 分析构造函数的调用情况:

    在MyBean的构造函数打上断点,debug运行,我们发现构造函数的调用时机是在 AbstractApplicationContext类中的refresh()方法里面调用了finishBeanFactoryInitialization()方法

  • 分析 MyBean 实现的InitializingBean 接口实现方法afterPropertiesSet 初始化方法调用情况

    System.out.println("afterPropertiesSet执行了......");打上断点,我们观察调用栈,MyBean 实现的InitializingBean 接口实现方法afterPropertiesSet 初始化方法的调用时机也是在AbstractApplicationContext类中的refresh()方法里面调用了finishBeanFactoryInitialization()方法

  • SpringBean工厂的后置处理器的BeanFactoryPostProcessor的构造器、postProcessBeanFactory方法是哪个方法调用的?

    方法同上,在对应代码出打上断点,debug运行,观察调用栈,发现是在

    AbstractApplicationContext#refresh()#invokeBeanFactoryPostProcessors 处调用的

  • SpringBean的后置处理器BeanPostProcessor的构造方法是哪个方法调用的?

    AbstractApplicationContext#refresh()#registerBeanPostProcessors 处调用的

  • SpringBean的后置处理器BeanPostProcessor的Before和after方法是哪个方法调用的?

    AbstractApplicationContext#refresh()#finishBeanFactoryInitialization 处调用的

总结:

根据上面的调试分析,我们发现Bean对象创建的几个关键时机点代码层级的调用都在 AbstractApplicationContext 类 的 refresh 方法中,可见这个方法对于SpringIOC容器初始化来说相当关键,汇总如下:

关键点触发代码
构造函数refresh#finishBeanFactoryInitialization(beanFactory)(beanFactory)
BeanFactoryPostProcessor 初始化refresh#invokeBeanFactoryPostProcessors(beanFactory)
BeanFactoryPostProcessor ⽅法调⽤refresh#invokeBeanFactoryPostProcessors(beanFactory)
BeanPostProcessor 初始化registerBeanPostProcessors(beanFactory)
BeanPostProcessor ⽅法调⽤refresh#finishBeanFactoryInitialization(beanFactory)

SpringIOC容器初始化主流程

由上分析可知,SpringIOC容器初始化的关键环节就在 **AbstractApplicationContext#refresh() **方法中,我们查看refresh方法来俯瞰容器创建的主题流程。

	@Override
	public void refresh() throws BeansException, IllegalStateException {
		// 对象锁加锁  refresh()、registerShutdownHook()、close()时加锁
		synchronized (this.startupShutdownMonitor) {
			/*
				Prepare this context for refreshing.
				刷新前的预处理
				表示在真正做refresh操作之前需要准备做的事情:
					设置Spring容器的启动时间
					开启活跃状态,撤销关闭状态
					验证环境信息里一些必须存在的属性等
			 */
			prepareRefresh();

			/*
				Tell the subclass to refresh the internal bean factory.
				获取BeanFactory,默认实现是DefaultListableBeanFactory
				加载BeanDefinition 并注册到BeanDefinitionRegistry
			 */
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			/*
				Prepare the bean factory for use in this context.
				BeanFactory的预准备工作(BeanFactory进行一些设置,比如context的类加载器等)
			 */
 			prepareBeanFactory(beanFactory);

			try {
				/*
				 	Allows post-processing of the bean factory in context subclasses.
				 	BeanFactory准备工作完成后的后置处理工作
				 */
				postProcessBeanFactory(beanFactory);

				/*
				 	Invoke factory processors registered as beans in the context.
				 	实例化实现了BeanFactoryPostProcessor接口的bean,并调用接口方法
				 */
				invokeBeanFactoryPostProcessors(beanFactory);

				/*
				 	Register bean processors that intercept bean creation.
				 	注册BeanPostProcessor(Bean的后置处理器),在创建Bean的前后等执行
				 */
				registerBeanPostProcessors(beanFactory);

				/*
				 	Initialize message source for this context.
				 	初始化MessageSource组件(做国际化功能:消息绑定,消息解析)
				 */
				initMessageSource();

				/*
				 	Initialize event multicaster for this context.
				 	初始化事件派发器
				 */
				initApplicationEventMulticaster();

				/*
				 	Initialize other special beans in specific context subclasses.
				 	子类重写这个方法,在容器刷新的时候可以自定义逻辑;如创建Tomcat、jetty等web服务器
				 */
				onRefresh();

				/*
				 	Check for listener beans and register them.
				 	注册应用的监听器,就是注册实现了ApplicationListener接口的监听器bean
				 */
				registerListeners();

				/*
				 	Instantiate all remaining (non-lazy-init) singletons.
				 	初始化所有剩下的非延迟加载的单例bean
				 	初始化创建非延迟加载的单例bean实例(未设置属性)
				 	填充属性
				 	初始化方法调用(比如调用afterPropertiesSet方法、init-method方法)
				 	调用BeanPostProcessor(后置处理器)对实例bean进行后置处理
				 */
				finishBeanFactoryInitialization(beanFactory);

				/*
				 	Last step: publish corresponding event.
				 	完成context的刷新。主要调用LifecycleProcessor的onRefresh()方法,并且发布事件(ContextRefreshedEvent)
				 */
				finishRefresh();
			}
            
            ......

		}
	}
BeanFactory创建流程
获取BeanFactory子流程

时序图如下:
在这里插入图片描述

BeanDefinition加载解析及注册子流程
  • 该子流程涉及到如下几个关键步骤:

    • Resource定位:指对BeanDefinition 的资源定位过程。通俗讲就是找到定义JavaBean信息的xml文件,并将其封装成Resource对象
    • BeanDefinition 载入:把用户定义好的JavaBean表示为IOC容器内部的数据结构,这个容器内部是数据结构就是BeanDefinition
    • 注册BeanDefinition 到IOC容器
  • 过程分析

    • step1:子流程入口在 AbstractRefreshableApplicationContext#refreshBeanFactory 方法中

      	@Override
      	protected final void refreshBeanFactory() throws BeansException {
      		// 判断是否已有BeanFactory
      		if (hasBeanFactory()) {
      			// 销毁 beans
      			destroyBeans();
      			// 关闭 BeanFactory
      			closeBeanFactory();
      		}
      		try {
      			// 实例化 DefaultListableBeanFactory
      			DefaultListableBeanFactory beanFactory = createBeanFactory();
      			// 设置序列化ID
      			beanFactory.setSerializationId(getId());
      			// 自定义bean工厂的一些属性(是否覆盖、是否允许循环依赖)
      			customizeBeanFactory(beanFactory);
      			// 加载应用中的BeanDefinition   
      			loadBeanDefinitions(beanFactory);  // 注意这里就是入口
      			// 赋值
      			this.beanFactory = beanFactory;
      		}
      		catch (IOException ex) {
      			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
      		}
      	}
      
    • step2:依次调用多个类的 loadBeanDefinitions 方法 —> AbstractXmlApplicationContext —> AbstractBeanDefinitionReader —> XmlBeanDefinitionReader ⼀直执行到 XmlBeanDefinitionReader 的 doLoadBeanDefinitions 方法

      protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
          throws BeanDefinitionStoreException {
      
          try {
              // 读取xml信息,将xml信息保存到Document对象
              Document doc = doLoadDocument(inputSource, resource);
              // 解析document对象,封装BeanDefinition对象并进行注册
              int count = registerBeanDefinitions(doc, resource);
              if (logger.isDebugEnabled()) {
                  logger.debug("Loaded " + count + " bean definitions from " + resource);
              }
              return count;
          }
      }
      
    • step3:我们重点观察XMLBeanDefinitionReader 类的 registerBeanDefinition 方法,期间产生了多次重载调用,我们定位到最后一个

      public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
          BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
          // 获取已有BeanDefinition的数量
          int countBefore = getRegistry().getBeanDefinitionCount();
          // 注册BeanDefinition
          documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
          // 返回新注册的BeanDefinition
          return getRegistry().getBeanDefinitionCount() - countBefore;
      }
      

      此处我们关注两个地方:createReaderContextregisterBeanDefinitions

      • createReaderContext

        public XmlReaderContext createReaderContext(Resource resource) {
            return new XmlReaderContext(resource, this.problemReporter, this.eventListener,this.sourceExtractor, this, getNamespaceHandlerResolver());
        }
        
        /**
        	 * Lazily create a default NamespaceHandlerResolver, if not set before.
        	 * @see #createDefaultNamespaceHandlerResolver()
        	 */
        public NamespaceHandlerResolver getNamespaceHandlerResolver() {
            if (this.namespaceHandlerResolver == null) {
                this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
            }
            return this.namespaceHandlerResolver;
        }
        
        /**
        	 * Create the default implementation of {@link NamespaceHandlerResolver} used if none is specified.
        	 * <p>The default implementation returns an instance of {@link DefaultNamespaceHandlerResolver}.
        	 * @see DefaultNamespaceHandlerResolver#DefaultNamespaceHandlerResolver(ClassLoader)
        	 */
        protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
            ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader());
            return new DefaultNamespaceHandlerResolver(cl);
        }
        

        我们可以看到,此处Spring首先完成了 NamespaceHandlerResolve 的初始化

      • 我们再进入 registerBeanDefinitions 方法中追踪,调用了 DefaultBeanDefinitionDocumentReader#registerBeanDefinitions 方法

        @Override
        public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
            this.readerContext = readerContext;
            doRegisterBeanDefinitions(doc.getDocumentElement());
        }
        

        进入 doRegisterBeanDefinitions 方法:

        protected void doRegisterBeanDefinitions(Element root) {
        
        	......
        
            preProcessXml(root);	
            parseBeanDefinitions(root, this.delegate);	// 重点
            postProcessXml(root);
        
            this.delegate = parent;
        }
        

        进入 parseBeanDefinitions 方法后再进入 parseDefaultElement 方法:

        private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
            // import元素处理
            if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
                importBeanDefinitionResource(ele);
            }
            // alias元素处理
            else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
                processAliasRegistration(ele);
            }
            // bean元素处理
            else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
                processBeanDefinition(ele, delegate);	// 这里就是解析bean元素
            }
            // 嵌套beans处理
            else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
                // recurse
                doRegisterBeanDefinitions(ele);
            }
        }
        

        进入 processBeanDefinition 方法:

        protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
            // 解析bean元素为BeanDefinition,但是此时使用 BeanDefinitionHolder 又包装成了 BeanDefinitionHolder对象
            BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
            if (bdHolder != null) {
                /*
        				<bean id="myBean" class="com.myspring.demo.MyBean">
        					<property name="beanName" value="bean demo"/>
        					<meta key="demo" value="demo"/>
        					<mybean:username="mybean"/>
        				</bean>
        				如果有自定义标签,则处理自定义标签
        			 */
                bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
                try {
                    // Register the final decorated instance.
                    // 完成BeanDefinition的注册
                    BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
                }
                catch (BeanDefinitionStoreException ex) {
        		......
            }
        }
        

至此,注册流程结束,我们发现,所谓的注册就是把封装的XML中定义的Bean信息封装为BeanDefinition对象后放入一个Map中,BeanFactory 是以Map的结构组织这些BeanDefinition的

可以在 DefaultListableBeanFactory#registerBeanDefinition 看到此Map的定义

/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
Bean创建流程

通过最开始的关键时机点分析,我们知道Bean创建子流程入口在 AbstractApplicationContext#refresh()⽅法的finishBeanFactoryInitialization(beanFactory)

@Override
public void refresh() throws BeansException, IllegalStateException {
    ......

    /*
		Instantiate all remaining (non-lazy-init) singletons.
		初始化所有剩下的非懒加载的单例bean
		初始化创建非懒加载的单例bean实例(未设置属性)
		填充属性
		初始化方法调用(比如调用afterPropertiesSet方法、init-method方法)
		调用BeanPostProcessor(后置处理器)对实例bean进行后置处理
	*/
    finishBeanFactoryInitialization(beanFactory); // bean创建入口

    ......

}

进入finishBeanFactoryInitialization 方法

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {

    ......

	// Instantiate all remaining (non-lazy-init) singletons.
	// 实例化所有立即加载的单例bean
	beanFactory.preInstantiateSingletons();
}

继续进入 DefaultListableBeanFactory 类的 preInstantiateSingletons 方法:

@Override
public void preInstantiateSingletons() throws BeansException {

    ......

    if (bean instanceof FactoryBean) {
        final FactoryBean<?> factory = (FactoryBean<?>) bean;
        boolean isEagerInit;
        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
            isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());
        }
        else {
            isEagerInit = (factory instanceof SmartFactoryBean &&
                           ((SmartFactoryBean<?>) factory).isEagerInit());
        }
        if (isEagerInit) {
            getBean(beanName);
        }
    }
    else {
        // 实例化当前bean
        getBean(beanName);
    }
    
    ......

}

可以看到工厂bean或者普通bean,最终都是通过 getBean 的方法获取实例

继续跟踪下去,我们进入到了 AbstractBeanFactory#doGetBean 方法,这个方法中的代码很多,我们直接找到核心部分

// 创建单例bean
if (mbd.isSingleton()) {
    sharedInstance = getSingleton(beanName, () -> {
        try {
            // 创建bean
            return createBean(beanName, mbd, args);
        }
        catch (BeansException ex) {
            // Explicitly remove instance from singleton cache: It might have been put there
            // eagerly by the creation process, to allow for circular reference resolution.
            // Also remove any beans that received a temporary reference to the bean.
            destroySingleton(beanName);
            throw ex;
        }
    });
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

接着进入到 AbstractAutowireCapableBeanFactory#createBean() 方法

try {
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    if (logger.isTraceEnabled()) {
        logger.trace("Finished creating instance of bean '" + beanName + "'");
    }
    return beanInstance;
}

进入 doCreateBean 方法看看,该方法我们关注两块重点区域

  • 创建Bean实例,此时未设置属性
if (instanceWrapper == null) {
    // 创建bean实例,但是尚未设置属性
    instanceWrapper = createBeanInstance(beanName, mbd, args);
}
  • 初始化bean
// 初始化bean实例
Object exposedObject = bean;
try {
    // bean属性填充
    populateBean(beanName, mbd, instanceWrapper);
    // 调用初始化方法,应用BeanPostProcessor后置处理器
    exposedObject = initializeBean(beanName, exposedObject, mbd);
}

到此,SpringIOC容器的初始化流程源码大概就看完了,源码内容非常多,调试起来还是有点懵的,建议多debug几次,不用看每一行代码,只需看下每个函数的主要功能即可。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值