千家信息网

Spring bean的详细创建过程

发表于:2024-10-14 作者:千家信息网编辑
千家信息网最后更新 2024年10月14日,本篇内容介绍了"Spring bean的详细创建过程"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!前
千家信息网最后更新 2024年10月14日Spring bean的详细创建过程

本篇内容介绍了"Spring bean的详细创建过程"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

前言

本篇文章所使用的 spring-context 版本是 5.0.6.RELEASE。

doGetBean

protected  T doGetBean(final String name, @Nullable final Class requiredType,                        @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {                final String beanName = transformedBeanName(name);                Object bean;                // Eagerly check singleton cache for manually registered singletons.                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 + "'");                                }                        }                        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);                }                else {                        // Fail if we're already creating this bean instance:                        // We're assumably within a circular reference.                        if (isPrototypeCurrentlyInCreation(beanName)) {                                throw new BeanCurrentlyInCreationException(beanName);                        }                        // Check if bean definition exists in this factory.                        BeanFactory parentBeanFactory = getParentBeanFactory();                        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) {                                markBeanAsCreated(beanName);                        }                        try {                                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);                                checkMergedBeanDefinition(mbd, beanName, args);                                // Guarantee initialization of beans that the current bean depends on.                                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()) {                                        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;                                                }                                        });                                        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);                                }                                else if (mbd.isPrototype()) {                                        // It's a prototype -> create a new instance.                                        Object prototypeInstance = null;                                        try {                                                beforePrototypeCreation(beanName);                                                prototypeInstance = createBean(beanName, mbd, args);                                        }                                        finally {                                                afterPrototypeCreation(beanName);                                        }                                        bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);                                }                                else {                                        String scopeName = mbd.getScope();                                        final Scope scope = this.scopes.get(scopeName);                                        if (scope == null) {                                                throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");                                        }                                        try {                                                Object scopedInstance = scope.get(beanName, () -> {                                                        beforePrototypeCreation(beanName);                                                        try {                                                                return createBean(beanName, mbd, args);                                                        }                                                        finally {                                                                afterPrototypeCreation(beanName);                                                        }                                                });                                                bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);                                        }                                        catch (IllegalStateException ex) {                                                throw new BeanCreationException(beanName,                                                                "Scope '" + scopeName + "' is not active for the current thread; consider " +                                                                "defining a scoped proxy for this bean if you intend to refer to it from a singleton",                                                                ex);                                        }                                }                        }                        catch (BeansException ex) {                                cleanupAfterBeanCreationFailure(beanName);                                throw ex;                        }                }                // Check if required type matches the type of the actual bean instance.                if (requiredType != null && !requiredType.isInstance(bean)) {                        try {                                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);                                if (convertedBean == null) {                                        throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());                                }                                return convertedBean;                        }                        catch (TypeMismatchException ex) {                                if (logger.isDebugEnabled()) {                                        logger.debug("Failed to convert bean '" + name + "' to required type '" +                                                        ClassUtils.getQualifiedName(requiredType) + "'", ex);                                }                                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());                        }                }                return (T) bean;        }

createBean

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)                        throws BeanCreationException {                if (logger.isDebugEnabled()) {                        logger.debug("Creating instance of bean '" + beanName + "'");                }                RootBeanDefinition mbdToUse = mbd;                // Make sure bean class is actually resolved at this point, and                // clone the bean definition in case of a dynamically resolved Class                // which cannot be stored in the shared merged bean definition.                // ???                Class resolvedClass = resolveBeanClass(mbd, beanName);                if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {                        mbdToUse = new RootBeanDefinition(mbd);                        mbdToUse.setBeanClass(resolvedClass);                }                // *** Prepare method overrides.                try {                        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.                        // ??? 动态代理的后置处理器在这里会进行 aspect 等的解析,将解析结果放到 xml 中。                        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 的生命周期                        Object beanInstance = doCreateBean(beanName, mbdToUse, args);                        if (logger.isDebugEnabled()) {                                logger.debug("Finished creating instance of bean '" + beanName + "'");                        }                        return beanInstance;                }                catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {                        // A previously detected exception with proper bean creation context already,                        // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.                        throw ex;                }                catch (Throwable ex) {                        throw new BeanCreationException(                                        mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);                }        }

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) {                    // ☆ 1.Instantiate the bean.                     instanceWrapper = createBeanInstance(beanName, mbd, args);                }                final Object bean = instanceWrapper.getWrappedInstance();                Class beanType = instanceWrapper.getWrappedClass();                if (beanType != NullBean.class) {                        mbd.resolvedTargetType = beanType;                }                // Allow post-processors to modify the merged bean definition.                synchronized (mbd.postProcessingLock) {                        if (!mbd.postProcessed) {                                try {                                        applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);                                }                                catch (Throwable ex) {                                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,                                                        "Post-processing of merged bean definition failed", ex);                                }                                mbd.postProcessed = true;                        }                }                // Eagerly cache singletons to be able to resolve circular references                // even when triggered by lifecycle interfaces like BeanFactoryAware.                // 是否暴露没有完成创建过程的 bean 的引用                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, () -> getEarlyBeanReference(beanName, mbd, bean));                }                // ☆ 2.Initialize the bean instance. 初始化 bean 实例可以分为两部分:☆ 2.1、☆ 2.2                Object exposedObject = bean;                try {                        // ☆ 2.1 填充实例化后 bean 的属性,执行部分 spring 内置 BeanPostProcessors.                        populateBean(beanName, mbd, instanceWrapper);                        // ☆ 2.2 执行 bean 拥有的初始化方法以及 spring 内置和我们自定义的 BeanPostProcessors.                        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 完全被创建成功后做一个检查,防止在循环引用的情况下提前暴露的 early bean (只是 new 出来还没有填充属性,也就是只完成了 ☆ 1)和 final bean (new 出来并完成了初始化,也就是完成了 ☆ 1、☆ 2)引用不一致。                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 actualDependentBeans = new LinkedHashSet<>(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.                // 注册 bean 的 disposable 后置处理器(spring ioc 容器 close 时,会执行 bean 的销毁 callback).                // callback 可以理解为你先注册一个逻辑到 spring ioc 容器中,它会在某个事件触发时(比如:close 时)执行这个 callback 逻辑。                try {                        registerDisposableBeanIfNecessary(beanName, bean, mbd);                }                catch (BeanDefinitionValidationException ex) {                        throw new BeanCreationException(                                        mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);                }                return exposedObject;        }

bean 后置处理器的执行时机

1. createBeanInstance

??? 待补充

2.populateBean

填充属性阶段会执行下列几个 bean 后置处理器:

  • AutowiredAnnotationBeanPostProcessor

  • InstantiationAwareBeanPostProcessor

3.initializeBean

执行初始化方法阶段会执行下列几个 bean 后置处理器:

  • CommonAnnotationBeanPostProcessor

当然除了这些还有我们自定义的 bean 后置处理器。

createBeanInstance

创建 bean 实例的 4 种方式

  1. instanceSupplier

通过一个 lambda 表达式去创建 bean 实例

  1. FactoryMethod

通过工厂方法创建 bean 实例,在 @Configuration 类中加了 @Bean 的方法其实就是工厂方法

  1. autowireConstructor

以构造器的方式自动装配创建 bean 实例,当一个类中有多个构造器时,spring ioc 容器会帮我们通过它的算法选择出一个最适合的构造器去创建 bean 实例。

  1. instantiateBean

采用无参的默认构造器创建 bean 实例

对应的具体实现我已经在下面代码中用 ☆ 标记,大家有兴趣可以看一下。

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {                // Make sure bean class is actually resolved at this point.                Class beanClass = resolveBeanClass(mbd, beanName);                if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,                                        "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());                }                // ☆ 1. instanceSupplier                Supplier instanceSupplier = mbd.getInstanceSupplier();                if (instanceSupplier != null) {                        return obtainFromSupplier(instanceSupplier, beanName);                }                // ☆ 2. instanceSupplier                if (mbd.getFactoryMethodName() != null)  {                        return instantiateUsingFactoryMethod(beanName, mbd, args);                }                // Shortcut when re-creating the same bean...                boolean resolved = false;                boolean autowireNecessary = false;                if (args == null) {                        synchronized (mbd.constructorArgumentLock) {                                if (mbd.resolvedConstructorOrFactoryMethod != null) {                                        resolved = true;                                        autowireNecessary = mbd.constructorArgumentsResolved;                                }                        }                }                if (resolved) {                        if (autowireNecessary) {                                return autowireConstructor(beanName, mbd, null, null);                        }                        else {                                return instantiateBean(beanName, mbd);                        }                }                // Need to determine the constructor...                Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);                if (ctors != null ||                                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||                                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {                        // ☆ 3. autowireConstructor                        return autowireConstructor(beanName, mbd, ctors, args);                }                // No special handling: simply use no-arg constructor.                // ☆ 4. instantiateBean                return instantiateBean(beanName, mbd);        }

"Spring bean的详细创建过程"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

0