spring的finishBeanFactoryInitialization方法分析
spring源码版本5.0.5
概述
该方法会实例化所有剩余的非懒加载单例 bean。除了一些内部的 bean、实现了 BeanFactoryPostProcessor 接口的 bean、实现了 BeanPostProcessor 接口的 bean,其他的非懒加载单例 bean 都会在这个方法中被实例化,并且 BeanPostProcessor 的触发也是在这个方法中。
分析
跟踪到AbstractApplicationContext.refresh()方法,找到代码finishBeanFactoryInitialization(beanFactory)查看实现。
- protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
- // Initialize conversion service for this context.
- // 1.初始化此上下文的转换服务
- if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
- beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
- beanFactory.setConversionService(
- beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
- }
- // Register a default embedded value resolver if no bean post-processor
- // (such as a PropertyPlaceholderConfigurer bean) registered any before:
- // at this point, primarily for resolution in annotation attribute values.
- // 2.如果beanFactory之前没有注册嵌入值解析器,则注册默认的嵌入值解析器:主要用于注解属性值的解析
- if (!beanFactory.hasEmbeddedValueResolver()) {
- beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
- }
- // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
- // 3.初始化LoadTimeWeaverAware Bean实例对象
- String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
- for (String weaverAwareName : weaverAwareNames) {
- getBean(weaverAwareName);
- }
- // Stop using the temporary ClassLoader for type matching.
- beanFactory.setTempClassLoader(null);
- // Allow for caching all bean definition metadata, not expecting further changes.
- // 4.冻结所有bean定义,注册的bean定义不会被修改或进一步后处理,因为马上要创建 Bean 实例对象了
- beanFactory.freezeConfiguration();
- // Instantiate all remaining (non-lazy-init) singletons.
- // 5.实例化所有剩余(非懒加载)单例对象
- beanFactory.preInstantiateSingletons();
- }
继续跟踪到DefaultListableBeanFactory#preInstantiateSingletons
- public void preInstantiateSingletons() throws BeansException {
- if (this.logger.isDebugEnabled()) {
- this.logger.debug("Pre-instantiating singletons in " + this);
- }
- // Iterate over a copy to allow for init methods which in turn register new bean definitions.
- // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
- List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
- // Trigger initialization of all non-lazy singleton beans...
- //遍历beanNames,触发所有非懒加载单例bean的初始化
- for (String beanName : beanNames) {
- RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
- //Bean实例:不是抽象类 && 是单例 && 不是懒加载
- if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
- //判断beanName对应的bean是否为FactoryBean
- if (isFactoryBean(beanName)) {
- //通过getBean(&beanName)拿到的是FactoryBean本身;通过getBean(beanName)拿到的是FactoryBean创建的Bean实例
- Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
- if (bean instanceof FactoryBean) {
- final FactoryBean<?> factory = (FactoryBean<?>) bean;
- //判断这个FactoryBean是否希望急切的初始化
- 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 {
- //如果beanName对应的bean不是FactoryBean,只是普通Bean,通过beanName获取bean实例
- getBean(beanName);
- }
- }
- }
- ......
- }
要理解FactoryBean和Bean的区别
一般情况下,Spring 通过反射机制利用 bean 的 class 属性指定实现类来实例化 bean。而 FactoryBean 是一种特殊的 bean,它是个工厂 bean,可以自己创建 bean 实例,如果一个类实现了 FactoryBean 接口,则该类可以自己定义创建实例对象的方法,只需要实现它的 getObject() 方法。
注:很多中间件都利用 FactoryBean 来进行扩展。
引入了几个重要的缓存:
- mergedBeanDefinitions 缓存:beanName -> 合并的 bean 定义。
- beanDefinitionMap 缓存:beanName -> BeanDefinition。
- singletonObjects 缓存:beanName -> 单例 bean 对象。
- earlySingletonObjects 缓存:beanName -> 单例 bean 对象,该缓存存放的是早期单例 bean 对象,可以理解成还未进行属性填充、初始化。
- singletonFactories 缓存:beanName -> ObjectFactory。
- singletonsCurrentlyInCreation 缓存:当前正在创建单例 bean 对象的 beanName 集合。
继承跟踪到AbstractBeanFactory#doGetBean创建bean
- protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
- @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
- //解析beanName,主要是解析别名、去掉FactoryBean的前缀“&”
- final String beanName = transformedBeanName(name);
- Object bean;
- // Eagerly check singleton cache for manually registered singletons.
- //尝试从缓存中获取beanName对应的实例,通过缓存解决循环依赖问题
- Object sharedInstance = getSingleton(beanName);
- if (sharedInstance != null && args == null) {
- if (logger.isDebugEnabled()) {
- if (isSingletonCurrentlyInCreation(beanName)) {
- logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
- "' that is not fully initialized yet - a consequence of a circular reference");
- }
- else {
- logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
- }
- }
- //返回beanName对应的实例对象(主要用于FactoryBean的特殊处理,普通Bean会直接返回sharedInstance本身)
- bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
- }
- else {
- // Fail if we're already creating this bean instance:
- // We're assumably within a circular reference.
- // scope为prototype非单例的循环依赖校验:如果beanName已经正在创建Bean实例中,而此时我们又要再一次创建beanName的实例,则代表出现了循环依赖,需要抛出异常。
- // 例子:如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还未创建完的时候因为对于B的创建再次返回创建A,造成循环依赖
- if (isPrototypeCurrentlyInCreation(beanName)) {
- throw new BeanCurrentlyInCreationException(beanName);
- }
- // Check if bean definition exists in this factory.
- BeanFactory parentBeanFactory = getParentBeanFactory();
- //如果parentBeanFactory存在,并且beanName在当前BeanFactory不存在Bean定义,则尝试从parentBeanFactory中获取bean实例
- if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
- // Not found -> check parent.
- String nameToLookup = originalBeanName(name);
- if (parentBeanFactory instanceof AbstractBeanFactory) {
- return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
- nameToLookup, requiredType, args, typeCheckOnly);
- }
- else if (args != null) {
- // Delegation to parent with explicit args.
- return (T) parentBeanFactory.getBean(nameToLookup, args);
- }
- else {
- // No args -> delegate to standard getBean method.
- return parentBeanFactory.getBean(nameToLookup, requiredType);
- }
- }
- if (!typeCheckOnly) {
- //如果不是仅仅做类型检测,而是创建bean实例,这里要将beanName放到alreadyCreated缓存
- markBeanAsCreated(beanName);
- }
- try {
- final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
- checkMergedBeanDefinition(mbd, beanName, args);
- // Guarantee initialization of beans that the current bean depends on.
- //拿到当前bean依赖的bean名称集合,在实例化自己之前,需要先实例化自己依赖的bean,如使用@DependsOn
- String[] dependsOn = mbd.getDependsOn();
- if (dependsOn != null) {
- for (String dep : dependsOn) {
- if (isDependent(beanName, dep)) {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName,
- "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
- }
- registerDependentBean(dep, beanName);
- try {
- getBean(dep);
- }
- catch (NoSuchBeanDefinitionException ex) {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName,
- "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
- }
- }
- }
- // Create bean instance.
- if (mbd.isSingleton()) {
- //scope为singleton的bean创建(新建了一个ObjectFactory,并且重写了getObject方法,在里面创建bean
- sharedInstance = getSingleton(beanName, () -> {
- try {
- 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;
- }
- });
- //返回beanName对应的实例对象
- bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
- }
- //其它非单例的情况,暂不分析
- ......
- }
- catch (BeansException ex) {
- cleanupAfterBeanCreationFailure(beanName);
- throw ex;
- }
- }
- ......
- return (T) bean;
- }
查看DefaultSingletonBeanRegistry#getSingleton
- public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
- Assert.notNull(beanName, "Bean name must not be null");
- synchronized (this.singletonObjects) {
- //首先检查beanName对应的bean实例是否在缓存中存在,如果已经存在,则直接返回
- Object singletonObject = this.singletonObjects.get(beanName);
- if (singletonObject == null) {
- if (this.singletonsCurrentlyInDestruction) {
- throw new BeanCreationNotAllowedException(beanName,
- "Singleton bean creation not allowed while singletons of this factory are in destruction " +
- "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
- }
- if (logger.isDebugEnabled()) {
- logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
- }
- //创建单例前的操作,把bean放入正准备创建的一个Set中singletonsCurrentlyInCreation,如果重复会报异常
- //如果存在构造器循环依赖的时候(A(B b),B(C c),C(A a)),会在这点报出异常
- beforeSingletonCreation(beanName);
- boolean newSingleton = false;
- boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
- if (recordSuppressedExceptions) {
- this.suppressedExceptions = new LinkedHashSet<>();
- }
- try {
- //执行singletonFactory的getObject方法获取bean实例,就是执行传入方法createBean
- singletonObject = singletonFactory.getObject();
- newSingleton = true;
- }
- ......
- finally {
- if (recordSuppressedExceptions) {
- this.suppressedExceptions = null;
- }
- //创建单例后的操作,在singletonsCurrentlyInCreation中移除
- afterSingletonCreation(beanName);
- }
- if (newSingleton) {
- addSingleton(beanName, singletonObject);
- }
- }
- return singletonObject;
- }
- }
继承跟踪AbstractAutowireCapableBeanFactory#createBean
- protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- throws BeanCreationException {
- ......
- try {
- //验证及准备覆盖的方法(对override属性进行标记及验证)
- mbdToUse.prepareMethodOverrides();
- }
- catch (BeanDefinitionValidationException ex) {
- throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
- beanName, "Validation of method overrides failed", ex);
- }
- try {
- // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
- //实例化前的处理,如果有实现InstantiationAwareBeanPostProcessor的BeanPostProcessor可以直接返回真正的bean实例
- Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
- if (bean != null) {
- return bean;
- }
- }
- catch (Throwable ex) {
- throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
- "BeanPostProcessor before instantiation of bean failed", ex);
- }
- try {
- //创建Bean实例(一般真正创建Bean的方法)
- Object beanInstance = doCreateBean(beanName, mbdToUse, args);
- if (logger.isDebugEnabled()) {
- logger.debug("Finished creating instance of bean '" + beanName + "'");
- }
- return beanInstance;
- }
- ......
- }
实例化前的处理,给 InstantiationAwareBeanPostProcessor 一个机会返回代理对象来替代真正的 bean 实例,从而跳过 Spring 默认的实例化过程,达到“短路”效果。会执行 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 方法,该方法可以返回 bean 实例的代理,从而跳过 Spring 默认的实例化过程。
查看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) {
- //根据beanName、mbd、args,使用对应的策略创建Bean实例,并返回包装类BeanWrappe
- instanceWrapper = createBeanInstance(beanName, mbd, args);
- }
- // todo !!!!!!!!这里获取出来的对象是原生对象!!!!!
- final Object bean = instanceWrapper.getWrappedInstance();
- Class<?> beanType = instanceWrapper.getWrappedClass();
- if (beanType != NullBean.class) {
- mbd.resolvedTargetType = beanType;
- }
- ......
- // Eagerly cache singletons to be able to resolve circular references
- // even when triggered by lifecycle interfaces like BeanFactoryAware.
- boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
- isSingletonCurrentlyInCreation(beanName));
- if (earlySingletonExposure) {
- if (logger.isDebugEnabled()) {
- logger.debug("Eagerly caching bean '" + beanName +
- "' to allow for resolving potential circular references");
- }
- //注意这点,曝光beanName的ObjectFactory,用于解决循环引用。 在开始通过doGetBean取值的时候调用了getSingleton就调用到这个工厂来了
- addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
- }
- // Initialize the bean instance.
- Object exposedObject = bean;
- try {
- //todo 对bean进行属性填充;其中,可能存在依赖于其他bean的属性,则会递归初始化依赖的bean实例
- //设置属性,非常重要,比如使用@Autowired注入的值等
- populateBean(beanName, mbd, instanceWrapper);
- // todo 经过AOP处理,原生对象转换成了代理对象,跟进去
- //执行后置处理器,aop就是在这里完成的处理
- exposedObject = initializeBean(beanName, exposedObject, mbd);
- }
- ......
- return exposedObject;
- }
实例化对象createBeanInstance,就是选出一个策略来实例化一个对象, 那有什么策略呢? 这就看程序员是怎么配置的了, 程序员可以配置工厂方法,指定构造方法,或者是程序员没有做出任何干涉,让Spring按自己的方式去实例化
参考:
https://www.cnblogs.com/ZhuChangwu/p/11755973.html
https://blog.csdn.net/v123411739/category_8589693.html
spring的finishBeanFactoryInitialization方法分析的更多相关文章
- Spring BeanFacoty doCreateBean方法分析
上一篇,我们分析到了doCreateBean,现在继续: 先看看时序图 protected Object doCreateBean(final String beanName, final RootB ...
- spring容器的refresh方法分析
spring源码版本5.0.5 Spring容器创建之后,会调用它的refresh方法刷新Spring应用的上下文. 首先整体查看AbstractApplicationContext#refresh源 ...
- Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean
Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean 七千字长文深刻解读,Spirng中是如何初始化单例bean的,和面试中最常问的Sprin ...
- Spring Ioc源码分析系列--容器实例化Bean的四种方法
Spring Ioc源码分析系列--实例化Bean的几种方法 前言 前面的文章Spring Ioc源码分析系列--Bean实例化过程(二)在讲解到bean真正通过那些方式实例化出来的时候,并没有继续分 ...
- spring IOC源码分析(ApplicationContext)
在上一篇文章中,我们以BeanFactory这条主线进行IOC的源码解析的,这里,将以ApplicationContext这条线进行分析.先看使用方法: @Test public void testA ...
- Spring IOC 源码分析
Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...
- Spring Boot源码分析-启动过程
Spring Boot作为目前最流行的Java开发框架,秉承"约定优于配置"原则,大大简化了Spring MVC繁琐的XML文件配置,基本实现零配置启动项目. 本文基于Spring ...
- SpringBoot框架——从SpringBoot看IoC容器初始化流程之方法分析
目录 一.概观Spring Boot 二.Spring Boot应用初始化 2.1 初始化入口 2.2 SpringApplication的run方法 2.3 方法分析 三.容器创建与初始化 3.1 ...
- 5.2 Spring5源码--Spring AOP源码分析二
目标: 1. 什么是AOP, 什么是AspectJ 2. 什么是Spring AOP 3. Spring AOP注解版实现原理 4. Spring AOP切面原理解析 一. 认识AOP及其使用 详见博 ...
随机推荐
- Hanlp-地名识别调试方法详解
HanLP收词特别是实体比较多,因此特别容易造成误识别.下边举几个地名误识别的例子,需要指出的是,后边的机构名识别也以地名识别为基础,因此,如果地名识别不准确,也会导致机构名识别不准确. 类型1 数字 ...
- 把Javascript 对象转换为键值对连接符字符串的方法总结
307down votefavorite 93 Do you know a fast and simple way to encode a Javascript Object into a strin ...
- Linux 下安装 redis5.0
1.redis 安装 wget http://download.redis.io/rele... tar -zxvf redis-5.0.5.tar.gz cd redis-5.0.5.tar.gz ...
- 如何使用RedisTemplate访问Redis数据结构之字符串操作
Redis 数据结构简介 Redis 可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字符串).List(列表).Set(集合).Hash(散列)和 Zset(有序集 ...
- (十一)springMvc 异常处理
文章目录 思路 自定义异常处理类 全局异常处理器 配置全局异常处理器 思路 在 springMvc 中,异常一层一层的往上抛,最后抛给 前端控制器,前端控制器内部会去找 全局异常处理器(一个系统只会有 ...
- Kindergarten(网络流解法)
题意:http://acm.hdu.edu.cn/showproblem.php?pid=2458 问你二分图的最大团是多大. #define IOS ios_base::sync_with_stdi ...
- 【深度森林第三弹】周志华等提出梯度提升决策树再胜DNN
[深度森林第三弹]周志华等提出梯度提升决策树再胜DNN 技术小能手 2018-06-04 14:39:46 浏览848 分布式 性能 神经网络 还记得周志华教授等人的“深度森林”论文吗?今天, ...
- mac 下 vscode配置SFTP连接
VScode中使用SFTP插件连接远程服务器进行文件修改 下载SFTP插件后,使用Ctrl+Shift+P.输入SFTP,选择第一个将会生成简短的默认配置文件 然后把sftp.json文件内内容换成以 ...
- c# 粘贴复制
复制 1. 复制 Clipboard.SetText("123456"); Clipboard.SetImage(Image img); Clipboard.SetAudio(Sy ...
- git遇到的问题记录2019.05.07
用sourcetree拉取代码,报错如下: error: cannot lock ref 'refs/remotes/origin/my_branch': unable to resolve refe ...