我的编程空间,编程开发者的网络收藏夹
学习永远不晚

spring初始化源码代码浅析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

spring初始化源码代码浅析

前言

在《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 constructor
    instanceWrapper = 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 method
         invokeCustomInitMethod(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初始化源码代码浅析的文章就介绍到这了,更多相关spring初始化源码内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

spring初始化源码代码浅析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

spring初始化源码代码浅析

Spring框架被广泛应用于我们的日常工作中,但是很长时间以来我们都是只会使用,不懂它的作用原理,下面这篇文章主要给大家介绍了关于spring初始化源码的相关资料,需要的朋友可以参考下
2023-05-18

SharedPreference初始化源码分析

本篇内容介绍了“SharedPreference初始化源码分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!初始化sp 内部将数据放到 xm
2023-07-05

tdesignvue初始化组件源码解析

这篇文章主要为大家介绍了tdesignvue初始化组件源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-12-21

initoutputstream初始化输出流源码分析

这篇文章主要为大家介绍了initoutputstream初始化输出流源码分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-11-13

Spring源码解析容器初始化构造的方法是什么

这篇“Spring源码解析容器初始化构造的方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Spring源码解析容器初
2023-07-02

如何进行SpringMVC源码中的初始化源码

如何进行SpringMVC源码中的初始化源码,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。所有Java的MVC框架都是基于servlet的,SpringMVC也不例外。它提供核
2023-06-02

分析Linux内核调度器源码之初始化

目录一、导语二、调度器的基本概念2.1、运行队列(rq)2.2、调度类(sched_class)2.3、调度域(sched_domain)2.4、调度组(sched_group)2.5、根域(root_domain)2.6、组调度(grou
2022-06-03

Vue3源码分析组件挂载初始化props与slots

这篇文章主要为大家介绍了Vue3源码分析组件挂载初始化props与slots实例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-11-13

java对象初始化代码分享

这篇文章主要讲解了“java对象初始化代码分享”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java对象初始化代码分享”吧!一,实例变量的初始化这里首先介绍下创建对象的过程:类型为Dog的一
2023-05-30

spring初始化源码之关键类和扩展接口详解

Spring就是一个大工厂,可以将所有对象的创建和依赖关系的维护交给Spring管理,下面这篇文章主要给大家介绍了关于spring初始化源码之关键类和扩展接口的相关资料,需要的朋友可以参考下
2023-05-18

python深度学习tensorflow参数初始化initializer源码分析

本篇内容介绍了“python深度学习tensorflow参数初始化initializer源码分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成
2023-07-06

Tomcat9源代码浅析-环境搭建

1.概要Apache Tomcat是一个非常受欢迎的开源Web容器,使用Java语言开发。近期公司开始推行开源技术的应用,目前正在将Weblogic替换为Tomcat,我们称之为W2T。本系列为项目过程中对Tomcat 9源代码分析的记录,
2023-06-02

Spring源码剖析1:初探Spring IOC核心流程

本文大致地介绍了IOC容器的初始化过程,只列出了比较重要的过程和代码,可以从中看出IOC容器执行的大致流程。接下来的文章会更加深入剖析Bean容器如何解析xml,注册和初始化bean,以及如何获取bean实例等详细的过程。转自:http:/
2023-06-02

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录