目录

1、refresh()简介

2、关键代码跟踪

​2.1、obtainFreshBeanFactory()代码分析

2.2、invokeBeanFactoryPostProcessors(beanFactory)代码分析

2.3、registerBeanPostProcessors(beanFactory)代码分析

2.4、registerListeners()代码分析

2.5、finishBeanFactoryInitialization(beanFactory)代码分析

2.4、finishRefresh()代码分析


在《spring初始化源码浅析之关键类和扩展接口》中主要是关键类和扩展接口的介绍,本文主要是debug代码来看spring是如何初始化以及在分别在何时输出上文 demo中各扩展点的日志。

本文分为两部分:《spring初始化源码浅析之关键类和扩展接口》、《spring初始化源码浅析之代码浅析》

1、refresh()简介

通过ClassPathXmlApplicationContext构造方法进入 refresh方法

public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//容器刷新前做一些准备工作prepareRefresh();// 创建DefaultListableBeanFactory对象,解析出所有BeanDefinition信息,//注册缓存在DefaultListableBeanFactory的beanDefinitionMap属性中,供后面创建bean对象时使用ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 为beanFactory提供一些标准配置,如:类加载器、环境变量等prepareBeanFactory(beanFactory);try {// 为beanFactory提供一些个性配置,通过在子上下文中复写该方法来实现postProcessBeanFactory(beanFactory);//创建实现BeanFactoryPostProcessor的实现类,并执行接口的方法。//该方法执行完后会输出实例中的1-7步的日志invokeBeanFactoryPostProcessors(beanFactory);//创建BeanPostProcessor的实现类,并注册到BeanFactoryPostProcessor的beanPostProcessors列表中,//在后面创建普通非lazy对象时会遍历该列表回调前置和后置方法registerBeanPostProcessors(beanFactory);//跟国际化消息相关,没去研究过initMessageSource();//初始化该上下文的事件广播initApplicationEventMulticaster();//模板方法,在不同的容器刷新的时候可以自定义逻辑onRefresh();//创建ApplicationListener的实现类,并注册到该上下文中registerListeners();//完成所有剩余的非lazy的bean的创建finishBeanFactoryInitialization(beanFactory);//上下文的创建完成的一些设置和缓存清理,并发布创建完成事件finishRefresh();}catch (BeansException ex) {……}finally {//Reset common introspection caches in Spring's core, since we//might not ever need metadata for singleton beans anymore...resetCommonCaches();}
}

2、关键代码跟踪

先看《spring初始化源码浅析之关键类和扩展接口》文中代码执行结果:

2.1、obtainFreshBeanFactory()代码分析

首先找到beanFactory的入口方法,如下

继续debug进入refreshBeanFactory方法,如下

从下图中可以看到,XmlBeanDefinitionReader为加载BeanDefinition的关键类,而将beanFactoy作为构造参数主要是为了将创建好的BeanDefinition对象注册到beanFactory中,后面会贴出相应的代码,如下

继续断点进入XmlBeanDefinitionReader的loadBeanDefinitions方法,可见入参为main方法中的指定配置文件的名称,如下

断点继续走,跳过将applicationContext.xml文件解析成Document的过程,进入registerBeanDefinitions(Document doc, Resource resource)方法,入参为applicationContext.xml对应的Document对象,该方法构造一个BeanDefinitionDocumentReader对象来具体的负责从doc对象创建BeanDefinition对象,并注册到beanFactory中,如下

注意 BeanDefinitionDocumentReader的registerBeanDefinitions方法一个入参为XmlReaderContext对象,该对象的reader即为前面创建XmlBeanDefinitionReader对象。

继续断点进入以下方法:

最后进入DefaultListableBeanFactory的registerBeanDefinition方法,最后将创建好的BeanDefinition对象缓存到DefaultListableBeanFactory的一个ConcurrentHashMap中

最终将配置文件中所有的bean配置转成BeanDefinition对象缓存起来,供后面创建具体的bean对象使用。

2.2、invokeBeanFactoryPostProcessors(beanFactory)代码分析

进入方法发现逻辑都交给PostProcessorRegistrationDelegate类来处理:

断点一直走到下面方法,先尝试从单利的缓存中去找,找不到再通过单例工厂类创建对象:

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {synchronized (this.singletonObjects) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {………………singletonObject = singletonFactory.getObject();newSingleton = true;…………if (newSingleton) {//添加到单例缓存中addSingleton(beanName, singletonObject);}}return singletonObject;}
} //由于缓存单例对象的 hashmap没有hellword对象,进入singletonFactory.getObject()方法 ,
//继续断点到 AbstractAutowireCapableBeanFactory的doCreateBean放法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {//创建bean对象的包装器,beanName=hellowordService,//该方法执行完成后输出第一步日志:1->HelloWorldService constructorinstanceWrapper = createBeanInstance(beanName, mbd, args);}final Object bean = instanceWrapper.getWrappedInstance();//创建bean对象…………try {//从RootBeanDefinition 获取属性信息并填充到instanceWrapper对象populateBean(beanName, mbd, instanceWrapper);//进入初始化bean对象的操作exposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}
}…………//将创建好的bean对象注册到缓存起来registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
…………
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {// 开始调用各种ware接口的方法,会输出2、3、4步的日志invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {//执行BeanPostProcessor的前置方法postProcessBeforeInitialization,由于//ApplicationContextAwareProcessor实现该接口,该类中会执行很多*Aware的类,而hellwordService//实现ApplicationContextAware类,所在会输出:4->ApplicationContextAware.setApplicationContext:wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {//init bean对象invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}if (mbd == null || !mbd.isSynthetic()) {//执行BeanPostProcessor的后置方法postProcessAfterInitialization,wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;
}
private void invokeAwareMethods(final String beanName, final Object bean) {if (bean instanceof Aware) {if (bean instanceof BeanNameAware) {//日志输出 2->BeanNameAware.setBeanName:helloWorldService((BeanNameAware) bean).setBeanName(beanName);}if (bean instanceof BeanClassLoaderAware) {ClassLoader bcl = getBeanClassLoader();if (bcl != null) {((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);}}if (bean instanceof BeanFactoryAware) {//日志输出 3->BeanFactoryAware.setBeanFactory:((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);}}
}…………protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)throws Throwable {boolean isInitializingBean = (bean instanceof InitializingBean);if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {if (logger.isTraceEnabled()) {logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");}if (System.getSecurityManager() != null) {try {AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {((InitializingBean) bean).afterPropertiesSet();return null;}, getAccessControlContext());}catch (PrivilegedActionException pae) {throw pae.getException();}}else {//日志输出:5->InitializingBean.afterPropertiesSet((InitializingBean) bean).afterPropertiesSet();}}if (mbd != null && bean.getClass() != NullBean.class) {String initMethodName = mbd.getInitMethodName();if (StringUtils.hasLength(initMethodName) &&!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&!mbd.isExternallyManagedInitMethod(initMethodName)) {//执行自定义init method方法,输出日志 :6->init methodinvokeCustomInitMethod(beanName, bean, mbd);}}}
}

最后回到getSingleton方法:

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {……//添加到单例缓存中addSingleton(beanName, singletonObject);
}

hellwordService对象创建完毕后,便执行 下一步的invokeBeanFactoryPostProcessors方法,输出第7步日志:
7->BeanFactoryPostProcessor.postProcessBeanFactory 将peopleService的content属性修改为i am ok

到此为止,invokeBeanFactoryPostProcessors(beanFactory);执行完毕

2.3、registerBeanPostProcessors(beanFactory)代码分析

可以看到代码和invokeBeanFactoryPostProcessors(beanFactory)的代码模式几乎一样,在本方法中会创建所有实现BeanPostProcessor接口类并注册到beanFactory中供后面对象创建时回调,代码不再做分析

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

2.4、registerListeners();代码分析

protected void registerListeners() {// Register statically specified listeners first.for (ApplicationListener<?> listener : getApplicationListeners()) {//hellowordService便在此处注册getApplicationEventMulticaster().addApplicationListener(listener);}
…………
}

2.5、finishBeanFactoryInitialization(beanFactory)代码分析

断点直接进入一下代码:
public void preInstantiateSingletons() throws BeansException {
   if (logger.isTraceEnabled()) {
      logger.trace("Pre-instantiating singletons in " + this);
   }
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

// Trigger initialization of all non-lazy singleton beans...
   for (String beanName : beanNames) {
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         if (isFactoryBean(beanName)) {
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            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 {
            //所有非lazy对象便在此处创建,如实例中的peopleServcie,对象创建过程前面已分析
           //peopleServcie的创建过程回掉beanpostProcessors的前置和后置方法,输出日志:
           //8->BeanPostProcessor.postProcessBeforeInitialization->peopleService
           //9->BeanPostProcessor.postProcessAfterInitialization->peopleService
            getBean(beanName);
         }
      }
   }
…………
}

2.4、finishRefresh()代码分析

protected void finishRefresh() {// Clear context-level resource caches (such as ASM metadata from scanning).clearResourceCaches();// Initialize lifecycle processor for this context.initLifecycleProcessor();// Propagate refresh to lifecycle processor first.getLifecycleProcessor().onRefresh();// Publish the final event.//发布ContextRefreshedEvent事件,输入日志//10->ApplicationListener.onApplicationEvent:publishEvent(new ContextRefreshedEvent(this));// Participate in LiveBeansView MBean, if active.LiveBeansView.registerApplicationContext(this);
}

到此代码分析完毕,以上只是简要的分析了初始化过程中关键代码,还有很多细节大家可自己断点跟踪。

spring初始化源码浅析之代码浅析相关推荐

  1. Spring 事务初始化源码分析

    前言 在上篇文章 Spring 事务使用详解 中详细介绍了 Spring 事务的使用过程,今天就来看下 Spring 事务是如何来实现,比如 Spring 事务在初始化的时候做了什么,Spring 事 ...

  2. 从Spring源码探究AOP代码织入的过程

    随着不断地使用Spring,以及后续的Boot.cloud,不断的体会到这个拯救Java的生态体系的强大,也使我对于这个框架有了极大的好奇心,以至于产生了我为什么不能写一个这样的框架的思考. 通过自学 ...

  3. Spring IoC容器初始化源码(1)—容器初始化入口以及setConfigLocations设置容器配置信息【一万字】

      基于最新Spring 5.x,对于基于XML的Spring IoC容器初始化过程中的setConfigLocations设置容器配置信息方法的源码进行了详细分析,最后给出了比较详细的方法调用时序图 ...

  4. 【源码阅读计划】浅析 Java 线程池工作原理及核心源码

    [源码阅读计划]浅析 Java 线程池工作原理及核心源码 为什么要用线程池? 线程池的设计 线程池如何维护自身状态? 线程池如何管理任务? execute函数执行过程(分配) getTask 函数(获 ...

  5. Spring Cloud源码分析(二)Ribbon(续)

    因文章长度限制,故分为两篇.上一篇:<Spring Cloud源码分析(二)Ribbon> 负载均衡策略 通过上一篇对Ribbon的源码解读,我们已经对Ribbon实现的负载均衡器以及其中 ...

  6. Quartz的Scheduler初始化源码分析

    2019独角兽企业重金招聘Python工程师标准>>> Quartz的使用:http://donald-draper.iteye.com/blog/2321886  Quartz的S ...

  7. Spring AOP 源码分析 - 拦截器链的执行过程

    1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...

  8. Spring AOP 源码分析 - 创建代理对象

    1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...

  9. Spring AOP 源码分析 - 筛选合适的通知器

    1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析.本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出 ...

最新文章

  1. Solr4.7从数据库导数据
  2. python collections(容器)模块
  3. Your Bitbucket account has been locked. To unlock it and log in again you must solve a CAPTCHA.
  4. 关于异常信息未找到成员
  5. poj 楼天成的男人八题系列 A New Stone Game 博弈问题
  6. Java中==和equals()的区别
  7. 过年倒计时 java swing 附源码
  8. Linux操作系统——桌面和终端基本操作【快捷键、一般模式、编辑模式、 命令模式】
  9. Equations of Mathematical Magic题解
  10. ubuntu下点云库pcl错误问题集
  11. 项目经理如何做好项目管理PMP - 持续更新
  12. SpringMVC 用对象接收 ajax提交form表单
  13. Vs2005中操作WORD
  14. DaVinci:跟踪器 - 窗口
  15. docker学习笔记(k8s云原生学习前瞻)
  16. linux热点连上不通,一个WiFi模块开出多个热点(不可连接)
  17. C#实现多语言切换详细教程(附源码)
  18. 360N5全网通QPST备份NV和恢复教程
  19. Python中字典的基本操作
  20. 简单实用的jQuery分页插件twbs-pagination

热门文章

  1. 国内邮箱品牌哪家好?
  2. Fiddler抓取手机端APP接口数据说明
  3. 【javascript】js实现表格全选功能
  4. VR云游带你玩转智慧文旅,解决景区营销痛点
  5. Python计算Linux服务器所有挂载磁盘的使用率
  6. RationalDMIS 2020测量圆
  7. sleep as android标签,Sleep as Android:终于、终于可以无痛起床
  8. 饿了么超时20分钟_美团、饿了么,你凭什么让我多等几分钟?
  9. asp实现注册登录界面_大明:手机怎样同时登录两个微信?教你方法,简单实用很有效...
  10. mysql 基本语句