Spring 源码分析 : 非懒加载的单例 Bean 初始化过程 ( 上 ) ( 2 )

接着第62行~第78行、第80行~第91行、第93行~第120行有三个判断,显然上面的MultiFunctionBean是一个单例的Bean也是本文探究的重点,因此执行第62行~第78行的逻辑。getSingleton方法不贴了,有一些前置的判断,很简单的逻辑,重点就是调用了ObjectFactory的getObject()方法来获取到单例Bean对象,方法的实现是调用了createBean方法,createBean方法是AbstractBeanFactory的子类AbstractAutowireCapableBeanFactory的一个方法,看一下它的方法实现:

 

protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)

        throws BeanCreationException {

 

    if (logger.isDebugEnabled()) {

        logger.debug("Creating instance of bean '" + beanName + "'");

    }

    // Make sure bean class is actually resolved at this point.

    resolveBeanClass(mbd, beanName);

 

    // Prepare method overrides.

    try {

        mbd.prepareMethodOverrides();

    }

    catch (BeanDefinitionValidationException ex) {

        throw new BeanDefinitionStoreException(mbd.getResourceDescription(),

                beanName, "Validation of method overrides failed", ex);

    }

 

    try {

        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.

        Object bean = resolveBeforeInstantiation(beanName, mbd);

        if (bean != null) {

            return bean;

        }

    }

    catch (Throwable ex) {

        throw new BeanCreationException(mbd.getResourceDescription(), beanName,

                "BeanPostProcessor before instantiation of bean failed", ex);

    }

 

    Object beanInstance = doCreateBean(beanName, mbd, args);

    if (logger.isDebugEnabled()) {

        logger.debug("Finished creating instance of bean '" + beanName + "'");

    }

    return beanInstance;

}

 

前面的代码都没什么意义,代码执行到第31行:

 

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {

    // Instantiate the bean.

    BeanWrapper instanceWrapper = null;

    if (mbd.isSingleton()) {

        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);

    }

    if (instanceWrapper == null) {

        instanceWrapper = createBeanInstance(beanName, mbd, args);

    }

    final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);

    Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

 

    // Allow post-processors to modify the merged bean definition.

    synchronized (mbd.postProcessingLock) {

        if (!mbd.postProcessed) {

            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

            mbd.postProcessed = true;

        }

    }

 

    // 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");

        }

        addSingletonFactory(beanName, new ObjectFactory() {

            public Object getObject() throws BeansException {

                return getEarlyBeanReference(beanName, mbd, bean);

            }

        });

    }

 

    // Initialize the bean instance.

    Object exposedObject = bean;

    try {

        populateBean(beanName, mbd, instanceWrapper);

        if (exposedObject != null) {

            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);

        }

    }

 

    if (earlySingletonExposure) {

        Object earlySingletonReference = getSingleton(beanName, false);

        if (earlySingletonReference != null) {

            if (exposedObject == bean) {

                exposedObject = earlySingletonReference;

            }

            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {

                String[] dependentBeans = getDependentBeans(beanName);

                Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);

                for (String dependentBean : dependentBeans) {

                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {

                        actualDependentBeans.add(dependentBean);

                    }

                }

                if (!actualDependentBeans.isEmpty()) {

                    throw new BeanCurrentlyInCreationException(beanName,

                            "Bean with name '" + beanName + "' has been injected into other beans [" +

                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +

                            "] in its raw version as part of a circular reference, but has eventually been " +

                            "wrapped. This means that said other beans do not use the final version of the " +

                            "bean. This is often the result of over-eager type matching - consider using " +

                            "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");

                }

            }

        }

    }

 

    // Register bean as disposable.

    try {

        registerDisposableBeanIfNecessary(beanName, bean, mbd);

    }

    catch (BeanDefinitionValidationException ex) {

        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);

    }

 

    return exposedObject;

}

 

代码跟踪到这里,已经到了主流程,接下来分段分析doCreateBean方法的代码。

 

创建Bean实例

 

第8行的createBeanInstance方法,会创建出Bean的实例,并包装为BeanWrapper,看一下createBeanInstance方法,只贴最后一段比较关键的:

 

// Need to determine the constructor...

Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

if (ctors != null ||

        mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||

        mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {

    return autowireConstructor(beanName, mbd, ctors, args);

}

 

// No special handling: simply use no-arg constructor.

return instantiateBean(beanName, mbd);

 

意思是bean标签使用构造函数注入属性的话,执行第6行,否则执行第10行。MultiFunctionBean使用默认构造函数,使用setter注入属性,因此执行第10行代码:

 

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {

    try {

        Object beanInstance;

        final BeanFactory parent = this;

        if (System.getSecurityManager() != null) {

            beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {

                public Object run() {

                    return getInstantiationStrategy().instantiate(mbd, beanName, parent);

                }

            }, getAccessControlContext());

        }

        else {

            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);

        }

        BeanWrapper bw = new BeanWrapperImpl(beanInstance);

        initBeanWrapper(bw);

        return bw;

    }

    catch (Throwable ex) {

        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);

    }

}

 

代码执行到13行:

 

public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {

    // Don't override the class with CGLIB if no overrides.

    if (beanDefinition.getMethodOverrides().isEmpty()) {

        Constructor<?> constructorToUse;

        synchronized (beanDefinition.constructorArgumentLock) {

            constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;

            if (constructorToUse == null) {

                final Class clazz = beanDefinition.getBeanClass();

                if (clazz.isInterface()) {

                    throw new BeanInstantiationException(clazz, "Specified class is an interface");

                }

                try {

                    if (System.getSecurityManager() != null) {

                        constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() {

                            public Constructor run() throws Exception {

                                return clazz.getDeclaredConstructor((Class[]) null);

                            }

                        });

                    }

                    else {

                        constructorToUse = clazz.getDeclaredConstructor((Class[]) null);

                    }

                    beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;

                }

                catch (Exception ex) {

                    throw new BeanInstantiationException(clazz, "No default constructor found", ex);

                }

            }

        }

        return BeanUtils.instantiateClass(constructorToUse);

    }

    else {

        // Must generate CGLIB subclass.

        return instantiateWithMethodInjection(beanDefinition, beanName, owner);

    }

}

 

整段代码都在做一件事情,就是选择一个使用的构造函数。当然第9行顺带做了一个判断:实例化一个接口将报错。

 

最后调用到30行,看一下代码:

 

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {

    Assert.notNull(ctor, "Constructor must not be null");

    try {

        ReflectionUtils.makeAccessible(ctor);

        return ctor.newInstance(args);

    }

    catch (InstantiationException ex) {

        throw new BeanInstantiationException(ctor.getDeclaringClass(),

                "Is it an abstract class?", ex);

    }

    catch (IllegalAccessException ex) {

        throw new BeanInstantiationException(ctor.getDeclaringClass(),

                "Is the constructor accessible?", ex);

    }

    catch (IllegalArgumentException ex) {

        throw new BeanInstantiationException(ctor.getDeclaringClass(),

                "Illegal arguments for constructor", ex);

    }

    catch (InvocationTargetException ex) {

        throw new BeanInstantiationException(ctor.getDeclaringClass(),

                "Constructor threw exception", ex.getTargetException());

    }

}

 

通过反射生成Bean的实例。看到前面有一步makeAccessible,这意味着即使Bean的构造函数是private、protected的,依然不影响Bean的构造。

 

最后注意一下,这里被实例化出来的Bean并不会直接返回,而是会被包装为BeanWrapper继续在后面使用。

 

来源:五月的仓颉,

www.cnblogs.com/xrq730/p/6361578.html

转载于:https://my.oschina.net/u/3100313/blog/889323

感应加热电源设计避坑指南:半桥LC串联谐振的5个关键问题 本文深入解析半桥LC串联谐振在感应加热电源设计中的5个关键问题,包括均压电阻选型、功率管驱动时序、谐振频率补偿等实战经验。通过真实故障案和解决方案,帮助工程师避开常见设计陷阱,提升电路稳定性和效率,特别适合从事桥感应加热电源开发的工程师参考。 阅读详情

相关推荐

Streamlit安装避坑指南:从零到一键启动你的第一个数据可视化应用

本文提供了一份详尽的Streamlit安装避坑指南,帮助用户从零开始快速启动第一个数据可视化应用。文章深入剖析了安装过程中常见的网络超时、依赖冲突、环境变量缺失等核心问题,并给出了使用虚拟环境、配置国内镜像源、利用.whl文件离线安装等多种经过验证的解决方案,确保安装过程顺畅无阻。

weixin_29065015的博客 596

Spring consider using ‘getBeanNamesOfType‘ with the ‘allowEagerInit‘ flag turned off, for example.

看下spring说的类,两个类之间发生循环引用了,请在一方的注入属性上添加@Lazy注解。避免循环引用。

cainiao1412的博客 1万+

Spring循环依赖源码解析

上篇文章中我们分析完了SpringBean的实过程,但是没有对循环依赖的问题进行分析,这篇文章中我们来看一下spring是如何解决循环依赖的实现。 之前在讲spring过程中,我们提到了一个spring池singletonObjects,用于存放创建好的bean,也提到过这个Map也可以说是狭义上的spring容器。 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<St

4816

@Async错误使用导致Spring循环依赖报错

注:首先如果程序中出现了循环依赖本身就是程序设计存在问题,尽量在设计上避免出现循环依赖。在springboot框架中已经默认不支持循环依赖的存在了,除设置spring.main.allow-circular-references=true 问题概述 This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching -

yangxiaofei_java的博客 7600

This is often the result of over-eager type matching - consider using ‘getBeanNamesForType‘

碰到循环依赖的,把类之间的关系理清楚,看看哪些是相互引用了,把循环引用给断了。这样是比较好的

一路向前 5076

循环依赖

问题描述:idea上将一个方法抽为公共方法,启动时候报错: This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off 说的是Bean名称重复了。检查了一番,莫名其妙没发现问题,idea没...

qq_33045443的博客 1750

Spring 源码分析 : 懒加载 Bean 初始化过程 () ( 2 )

Aware注入 接下来是Aware注入。在使用Spring的时候我们将自己的Bean实现BeanNameAware接口、BeanFactoryAware接口等,依赖容器帮我们注入当前Bean的名称或者Bean工厂,其代码实现先追溯到上面doCreateBean方法的42行initialize...

181

Spring源码分析】执行流程之懒加载Bean的实化逻辑

本文阐述了 getBean 的主要流程,Bean的生命周期主要呈现在 createBean中,实化前->加载类->实化->实化后->属性填充->初始化前->初始化->初始化后,当然每个阶段前后可能还有一些操作,比如一些解决循环依赖啊,用父工厂去进行操作等等等本篇博客没有提及,后续会进行对应的源码分析

qq_63691275的博客 1494

Spring生命周期Bean初始化过程详解

Spring声明周期Bean初始化过程详解Spring 容器初始化Spring Bean初始化BeanFactory和FactoryBean源码分析Bean的实化preInstantiateSingletonsgetMergedLocalBeanDefinitiongetBean方法getObjectForBeanInstance子分析@DependsOn Spring 容器初始化spring中,不管是以xml文件的方式配置的Bean还是以注解的方式进行配置,最后都会将Bean放入到Spring

JAVA技术爱好者 1万+

Spring源码分析懒加载Bean初始化过程(上篇)

代码入口 上文【Spring源码分析Bean加载流程概览,比较详细地分析了Spring上下文加载的代码入口,并且在AbstractApplicationContext的refresh方法中,点出了finishBeanFactoryInitialization方法完成了对于所有懒加载Bean初始化。 finishBeanFactoryInitialization方法中调用了DefaultListableBeanFactory的preInstantiateSingletons方法,本文针对preIn

310

spring 创建 Bean 源码分析

Spring Boot 2.6+ 默认禁止循环依赖以提升代码质量,开发者应优先通过设计消除依赖闭环。若需临时兼容,可通过配置文件或代码显式开启,但需明确此操作仅为过渡方案。

肢解生活,直达本质;凡所有相,皆是虚妄。 1309

Spring源码:ApplicationContext之提前加载Bean

一、介绍   标题中强调指出ApplicationContext,是因为使用Spring框架有两种方式:BeanFactory和ApplicationContext,代码如下: // beanFactory方式 @Test public void beanFactoryTest() { Resource classPathResource = new ClassPathResource("applicationContext.xml"); BeanFacto

咔咔学长 1573

spring懒加载bean源码分析

懒加载懒加载 懒加载指的是spring容器初始化的时候并不实,当用到的时候才实化,需要在标签上指定”lazy-init”属性值为true,用到的时候不只指 直接使用,或者是被别的懒加载bean依赖了。 赖加载指的是spring容器初始化的时候实bean,bean不限制是(singleton)还是多(prototype)但是都只实一个bean,一般bean都是懒加载,...

王者之峰 1235

Spring源码分析(二)-Spring IoC容器的初始化No.2

Spring源码分析(二)-Spring IoC容器的初始化No.2

qq418517226的专栏 2942

springBean的生命周期之生成懒加载Bean

一问从源码了解什么时候会创建懒加载Bean,FactoryBean有什么的特殊点!

qq_35436158的博客 372

Spring源码分析懒加载Bean初始化过程(下篇)

doCreateBean方法 上文【Spring源码分析懒加载Bean初始化过程(上篇),分析了Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实化出来的。先贴一下AbstractAutowireCapableBeanFactory的doCreateBean方法代码: 1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object

227

面试题:Spring为什么默认bean

Spring提供了5种scope分别是singleton、prototype、request、session、global session。 官方文档介绍: bean与原型bean的区别 :一个bean被声明为时,处理多次请求时spring容器里只实化一个bean,后续的请求公用这个对象,这个对象存储在一个map中,当有请求时,先在缓存中(map)查...

Lambda 6092

Spring 懒加载 Bean 生命周期源码分析

文章目录 /** * Create a new AnnotationConfigApplicationContext, deriving bean definitions * from the given annotated classes and automatically refreshing the context. * @param annotatedClasses one or more annotated classes, * e.g. {@link Configuratio

秀强的专栏 1032

getbean方法找不到bean_Spring 源码学习 - bean的实过程

本文作者:geek,一个聪明好学的同事1. 简介 开发中我们常用@Commpont,@Service,@Resource等注解或者配置xml去声明一个类,使其成为spring容器中的bean,以下我将用从源码角度看以AnnotationConfigApplicationContext为spring如何把带有注解的类生成springbean2. 示代码 public class Test...

weixin_39945792的博客 679

Spring源码分析bean加载流程

背景在Spring中,Bean的加载和管理是其核心功能之一,包括配置元数据解析、Bean定义注册、实化、属性填充、初始化、后置处理器处理、完成创建和销毁等步骤。源码入口AbstractBeanFactory#doGetBean具体源码流程如下:bean加载流程(#getBean方法)分析:1、提取beanName提取FactoryBean修饰符,比如name=“&aa”,那么就要去掉&a...

Diligence is the mother of success. 1609

Spring Bean的创建初始化过程源码分析

title: Spring Bean的创建初始化过程源码分析 date: 2020-04-20 19:59:24 tags:Spring bean的生命周期简来说: bean创建—初始化----销毁的过程 Bean的创建初始化 ​ 当完成了Spring容器的初始化以及BeanDefinition的搜集入库后,Spring就会开始一部分bean的创建与初始化。 (1)refresh()...

weixin_38950807的博客 513
上一篇: Spring 源码分析 : 非懒加载的单例 Bean 初始化过程 ( 上 ) ( 1 )
下一篇: Spring 源码分析 : 非懒加载的单例 Bean 初始化过程 ( 下 ) ( 1 )
chuba6693
博客等级 码龄9年 4粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值