Spring全家桶源码解析--2.2 Spring bean 的创建

news2024/10/6 18:22:08

文章目录

  • 前言
  • 一、Bean 的生成过程:
    • 1.1 创建过程:
      • 1.1.1 doGetBean 创建bean
      • 1.1.2 单例bean 创建getSingleton:
      • 1.1.3 单例bean 创建createBean:
      • 1.1.4 单例bean 创建doCreateBean:
      • 1.1.5 bean 实例化和初始化之后factoryBean 处理
    • 1.2 bean 的销毁:
      • 1.2.1 spring 容器关闭,通过close 关闭容器:
      • 1.2.2 销毁所有的单例 bean 通过 destroyBeans下destroySingletons:
  • 二、扩展点
    • 2.1 Bean 的实例化之前:
    • 2.2 Bean 的实例化之后属性注入之前:
    • 2.3 Bean 的属性注入后初始化:
    • 2.4 所有Bean实例化和初始化之后:
    • 2.5 Bean 的销毁:
  • 总结


前言

spring在启动时完成了对需要生成bean 的BeanDefinition 定义,在finishBeanFactoryInitialization(beanFactory) 对bean 进行生成,bean的生成过程中,spring 也提供一些扩展点供开发者使用,如在bean 的实例化之前,实例化之后,初始化之前,初始化之后,所有的bean 都完成实例化和初始化之后 均可以进行扩展。


一、Bean 的生成过程:

1.1 创建过程:

循环遍历所有的BeanDefinition 的map , 合并父类的bean 定义 得到一个新的 RootBeanDefinition,如果没有父类则直接 生成一个新的RootBeanDefinition ,放入到 Map<String, RootBeanDefinition> mergedBeanDefinitions map 中去,后续使用新的 RootBeanDefinition 进行bean 的创建;

注意BeanDefinition 合并的属性值:
如果子类没有的属性父亲有 则使用父亲的,但是如果是子类也有这个属性则进行覆盖;

1.1.1 doGetBean 创建bean

AbstractBeanFactory.doGetBean 去创建单例,原型 等bean

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
	// bean 名称获取 如果 name 以& 开头 最终也会去掉 & 符号,如果传入的bean name 是别名,则通过别名的
    // 的 map 获取bean的真正name并返回
    String beanName = this.transformedBeanName(name);
     // 从3级缓存获取bean
    Object sharedInstance = this.getSingleton(beanName);
    Object beanInstance;
    if (sharedInstance != null && args == null) {
         //  从缓存中获取到了bean 则处理后进行返回
        if (this.logger.isTraceEnabled()) {
            if (this.isSingletonCurrentlyInCreation(beanName)) {
                this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
            } else {
                this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }

        beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
    } else {
		//  创建bean
		// 检查bean 是否正在创建
        if (this.isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
		// 如果本身的beanfactory 中没有这个 bean 的 BeanDefinition
		// 如果有父的beanfactory  则尝试从父的beanfactory  获取bean 的 BeanDefinition
        BeanFactory parentBeanFactory = this.getParentBeanFactory();
        if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
 
            String nameToLookup = this.originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
            }

            if (args != null) {
                return parentBeanFactory.getBean(nameToLookup, args);
            }

            if (requiredType != null) {
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }

            return parentBeanFactory.getBean(nameToLookup);
        }
		// 标识这个bean 正在被创建
        if (!typeCheckOnly) {
            this.markBeanAsCreated(beanName);
        }

        StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);

        try {
            if (requiredType != null) {
                beanCreation.tag("beanType", requiredType::toString);
            }
			// 获取这个bean 合并后的 BeanDefinition
            RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
			// 检查是否是抽象的
            this.checkMergedBeanDefinition(mbd, beanName, args);
  			 // 获取 DependsOn 注解
            String[] dependsOn = mbd.getDependsOn();
            String[] prototypeInstance;
            if (dependsOn != null) {
				// 先创建DependsOn  注解的bean
                prototypeInstance = dependsOn;
                int var13 = dependsOn.length;

                for(int var14 = 0; var14 < var13; ++var14) {
                    String dep = prototypeInstance[var14];
					// 是否 DependsOn   的bean 是否依赖了 当前正在创建的bean 出现循环依赖则抛异常
                    if (this.isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
					// 添加 map 某个bean 被哪些bean 依赖了
					// private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap(64);
                    this.registerDependentBean(dep, beanName);

                    try {
						// 去获取 被依赖的bean 
                        this.getBean(dep);
                    } catch (NoSuchBeanDefinitionException var31) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var31);
                    }
                }
            }

            if (mbd.isSingleton()) {
				// bean是单例,创建单例bean 并放入到单例池中
                sharedInstance = this.getSingleton(beanName, () -> {
                    try {
                        return this.createBean(beanName, mbd, args);
                    } catch (BeansException var5) {
                        this.destroySingleton(beanName);
                        throw var5;
                    }
                });
                beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            } else if (mbd.isPrototype()) {
				// 如果是原型bean 则直接创建后进行返回,不放人单例池中
                prototypeInstance = null;

                Object prototypeInstance;
                try {
					// 当前bean 正在被创建标识
                    this.beforePrototypeCreation(beanName);
                    prototypeInstance = this.createBean(beanName, mbd, args);
                } finally {
					// 移除标识
                    this.afterPrototypeCreation(beanName);
                }

                beanInstance = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            } else {
				// 	其它bean 的作用域,bean 获取,如果session ,request 等如 @RequestScope 
                String scopeName = mbd.getScope();
                if (!StringUtils.hasLength(scopeName)) {
                    throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
                }

                Scope 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, () -> {
                        this.beforePrototypeCreation(beanName);

                        Object var4;
                        try {
                            var4 = this.createBean(beanName, mbd, args);
                        } finally {
                            this.afterPrototypeCreation(beanName);
                        }

                        return var4;
                    });
                    beanInstance = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                } catch (IllegalStateException var30) {
                    throw new ScopeNotActiveException(beanName, scopeName, var30);
                }
            }
        } catch (BeansException var32) {
            beanCreation.tag("exception", var32.getClass().toString());
            beanCreation.tag("message", String.valueOf(var32.getMessage()));
            this.cleanupAfterBeanCreationFailure(beanName);
            throw var32;
        } finally {
            beanCreation.end();
        }
    }

    return this.adaptBeanInstance(name, beanInstance, requiredType);
}

1.1.2 单例bean 创建getSingleton:

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    synchronized(this.singletonObjects) {
    	// 先尝试从单例池周中获取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 (this.logger.isDebugEnabled()) {
                this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
            }
			// 记录单例bean 正在被创建
            this.beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = this.suppressedExceptions == null;
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet();
            }

            try {
			   // 执行 lambda 表达式 调用  createBean 方法 创建一个对象
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            } catch (IllegalStateException var16) {
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    throw var16;
                }
            } catch (BeanCreationException var17) {
                BeanCreationException ex = var17;
                if (recordSuppressedExceptions) {
                    Iterator var8 = this.suppressedExceptions.iterator();

                    while(var8.hasNext()) {
                        Exception suppressedException = (Exception)var8.next();
                        ex.addRelatedCause(suppressedException);
                    }
                }

                throw ex;
            } finally {
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = null;
                }
				// 移除改单例bean 正在被创建标识
                this.afterSingletonCreation(beanName);
            }
			// 如果单例bean 创建成功,则添加进入单例池中
            if (newSingleton) {
                this.addSingleton(beanName, singletonObject);
            }
        }

        return singletonObject;
    }
}

1.1.3 单例bean 创建createBean:

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    if (this.logger.isTraceEnabled()) {
        this.logger.trace("Creating instance of bean '" + beanName + "'");
    }

    RootBeanDefinition mbdToUse = mbd;
	// 加载class 通过默认的appclassLoader 类加载器 加载到这个类 然后设置beanClass
    Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    try {
        mbdToUse.prepareMethodOverrides();
    } catch (BeanDefinitionValidationException var9) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var9);
    }

    Object beanInstance;
    try {
		// bean  实例化前做的工作
        beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
        if (beanInstance != null) {
			// 实例化前 由自定义的业务 返回了改对象 则直接返回改对象
            return beanInstance;
        }
    } catch (Throwable var10) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10);
    }

    try {
		// 创建bean
        beanInstance = this.doCreateBean(beanName, mbdToUse, args);
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
		// 返回bean
        return beanInstance;
    } catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {
        throw var7;
    } catch (Throwable var8) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8);
    }
}

1.1.4 单例bean 创建doCreateBean:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
    }

    if (instanceWrapper == null) {
		// 推断构造方法实例化对象
        instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    }

    Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    synchronized(mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
				//  处理合并好了的 BeanDefinition 后置处理器, 对 @Autowired ne @Value @Resource 进行预处理
				// 在bean 的实例化之后,做工作,如在BeanDefinition  定义初始化方法
                this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            } catch (Throwable var17) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
            }

            mbd.postProcessed = true;
        }
    }

    boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
    // 如果这个bean 可以提前暴露
    if (earlySingletonExposure) {
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
        }
        // 获取提前暴露出来的对象 并将beanfactory 放入到第3级缓存中
        this.addSingletonFactory(beanName, () -> {
            return this.getEarlyBeanReference(beanName, mbd, bean);
        });
    }

    Object exposedObject = bean;

    try {
         // 属性注入
        this.populateBean(beanName, mbd, instanceWrapper);
        // 执行bean 的初始化方法 如实现 InitializingBean 接口调用 afterPropertiesSet 方法
        exposedObject = this.initializeBean(beanName, exposedObject, mbd);
    } catch (Throwable var18) {
        if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
            throw (BeanCreationException)var18;
        }

        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
    }

    if (earlySingletonExposure) {
        Object earlySingletonReference = this.getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                String[] dependentBeans = this.getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                String[] var12 = dependentBeans;
                int var13 = dependentBeans.length;

                for(int var14 = 0; var14 < var13; ++var14) {
                    String dependentBean = var12[var14];
                    if (!this.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 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
                }
            }
        }
    }

    try {
        // bean 销毁逻辑赋值 destroy 方法,容器关闭时,销毁销毁bean 的过程中调用
        this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
        return exposedObject;
    } catch (BeanDefinitionValidationException var16) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
    }
}

1.1.5 bean 实例化和初始化之后factoryBean 处理

通过 getObjectForBeanInstance 方法对factoryBean 进行特殊处理

protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    if (BeanFactoryUtils.isFactoryDereference(name)) {
       // 如果 传递进来的原始的name 以& 开头则认为是一个factory  的bean
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        } else if (!(beanInstance instanceof FactoryBean)) {
            // 判断是否真的是factory  的bean 如果发现不是则抛出异常 针对业务本身getbean(“&xxxx”) 情况
            throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
        } else {
            if (mbd != null) {
                mbd.isFactoryBean = true;
            }

            return beanInstance;
        }
    } else if (!(beanInstance instanceof FactoryBean)) {
         // 普通的bean 则直接返回
        return beanInstance;
    } else {
       // 针对业务本身getbean(“xxxx”) 情况 虽然不以& 开头但是本身确实是factory的bean 
        Object object = null;
        if (mbd != null) {
            mbd.isFactoryBean = true;
        } else {
            object = this.getCachedObjectForFactoryBean(beanName);
        }
       // 从缓存中没有获取到bean
        if (object == null) {
            FactoryBean<?> factory = (FactoryBean)beanInstance;
            if (mbd == null && this.containsBeanDefinition(beanName)) {
                mbd = this.getMergedLocalBeanDefinition(beanName);
            }

            boolean synthetic = mbd != null && mbd.isSynthetic();
           // 最终调用改bean 对应类的object 方法获取bean
            object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
        }

        return object;
    }
}

1.2 bean 的销毁:

在这里插入图片描述

1.2.1 spring 容器关闭,通过close 关闭容器:

protected void doClose() {
    if (this.active.get() && this.closed.compareAndSet(false, true)) {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Closing " + this);
        }

        if (!NativeDetector.inNativeImage()) {
            LiveBeansView.unregisterApplicationContext(this);
        }

        try {
            // 发布容器关闭事件
            this.publishEvent((ApplicationEvent)(new ContextClosedEvent(this)));
        } catch (Throwable var3) {
            this.logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", var3);
        }

        if (this.lifecycleProcessor != null) {
            try {
                this.lifecycleProcessor.onClose();
            } catch (Throwable var2) {
                this.logger.warn("Exception thrown from LifecycleProcessor on context close", var2);
            }
        }
      // 销毁所有的单例 bean
        this.destroyBeans();
        this.closeBeanFactory();
        this.onClose();
        if (this.earlyApplicationListeners != null) {
            this.applicationListeners.clear();
            this.applicationListeners.addAll(this.earlyApplicationListeners);
        }

        this.active.set(false);
    }

}

1.2.2 销毁所有的单例 bean 通过 destroyBeans下destroySingletons:

public void destroySingletons() {
    if (this.logger.isTraceEnabled()) {
        this.logger.trace("Destroying singletons in " + this);
    }

    synchronized(this.singletonObjects) {
        this.singletonsCurrentlyInDestruction = true;
    }

    String[] disposableBeanNames;
    synchronized(this.disposableBeans) {
        disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
    }

    for(int i = disposableBeanNames.length - 1; i >= 0; --i) {
		//  遍历销毁每个单例bean 然后执行bean 的销毁方法 
        this.destroySingleton(disposableBeanNames[i]);
    }

    this.containedBeanMap.clear();
    this.dependentBeanMap.clear();
    this.dependenciesForBeanMap.clear();
	// 单例池清空
    this.clearSingletonCache();
}

// 单例池清空
protected void clearSingletonCache() {
    synchronized(this.singletonObjects) {
        this.singletonObjects.clear();
        this.singletonFactories.clear();
        this.earlySingletonObjects.clear();
        this.registeredSingletons.clear();
        this.singletonsCurrentlyInDestruction = false;
    }
}

二、扩展点

2.1 Bean 的实例化之前:

在这里插入图片描述

在创建bean 的过程中通过 resolveBeforeInstantiation 方法调用

@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
           // 这个是否实现了InstantiationAwareBeanPostProcessor
            Class<?> targetType = this.determineTargetType(beanName, mbd);
            if (targetType != null) {
                // 执行实例化之前的方法,遍历所以实现了InstantiationAwareBeanPostProcessor 接口的方法
                // 如果得到了返回值 当前类的实例化对象(业务自定义处理),则直接返回,否则遍历完成还没有则返回null
                bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if (bean != null) {
                    // 如果这个bean 进行了实例化,执行初始化之后方法
                    bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }

        mbd.beforeInstantiationResolved = bean != null;
    }

    return bean;
}

InstantiationAwareBeanPostProcessor是Spring的bean后置处理器,在bean实例化过程中的一些重要阶段提供了扩展点。这个接口继承自BeanPostProcessor,添加了实例化过程中的三个方法:

  • postProcessBeforeInstantiation: 此方法在Spring开始实例化bean之前调用,允许我们在Spring的默认实例化逻辑之前提供自定义实例化逻辑。如果这个方法返回一个非空对象,那么Spring会使用这个对象作为bean,而不再进行默认的实例化流程。

  • postProcessAfterInstantiation: 此方法在Spring实例化bean之后调用,允许我们在属性注入(依赖注入)前进行一些自定义操作。如果它返回false,那么Spring将跳过这个bean的属性注入步骤。

  • postProcessPropertyValues: 此方法在Spring进行依赖注入(属性注入)之前调用,允许我们对将要注入的属性做一些自定义处理。例如,我们可以修改这些待注入的属性。

2.2 Bean 的实例化之后属性注入之前:

在这里插入图片描述

在populateBean bean 属性注入的方法中通过 bp.postProcessAfterInstantiation 执行:

if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
	// 获取所有实现了InstantiationAwareBeanPostProcessor 接口进行遍历
    Iterator var4 = this.getBeanPostProcessorCache().instantiationAware.iterator();

    while(var4.hasNext()) {
        InstantiationAwareBeanPostProcessor bp = (InstantiationAwareBeanPostProcessor)var4.next();
		// 调用bean 的实例化之后的方法
        if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
            return;
        }
    }
}

postProcessAfterInstantiation: 此方法在Spring实例化bean之后调用,允许我们在属性注入(依赖注入)前进行一些自定义操作。如果它返回false,那么Spring将跳过这个bean的属性注入步骤;

2.3 Bean 的属性注入后初始化:

在这里插入图片描述
initializeBean 方法处理bean 在属性注入之后的逻辑

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged(() -> {
            this.invokeAwareMethods(beanName, bean);
            return null;
        }, this.getAccessControlContext());
    } else {
        this.invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
    	// 初始化之前调用 postProcessBeforeInitialization 
        wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
    }

    try {
    	// 初始化方法调用 isInitializingBean 接口实现的 afterPropertiesSet 方法
        this.invokeInitMethods(beanName, wrappedBean, mbd);
    } catch (Throwable var6) {
        throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
    }

    if (mbd == null || !mbd.isSynthetic()) {
   		 // 初始化之前调用 postProcessAfterInitialization
        wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

2.4 所有Bean实例化和初始化之后:

SmartInitializingSingleton 是 Spring 中的一个接口,主要的作用是对所有单例 bean(包括懒加载的 bean)进行回调。在 Spring 容器全局范围内,所有的单例 bean 都初始化完成后,它才会回调。

它只包含一个方法 afterSingletonsInstantiated,这个方法在所有单例 Bean 都准备就绪之后调用。这个接口通常用于在所有 Bean初始化完成后进行一些额外的校验或者预处理。相比@PostConstruct注解,该接口的回调更晚一些,所有单例bean都初始化完毕之后才调用。

可以使用 SmartInitializingSingleton 来确保 Spring 上下文中所需的所有依赖关系都已经设置完毕,或者你可以仅仅用它来检查应用的一致性。

2.5 Bean 的销毁:

在这里插入图片描述

bean 销毁逻辑赋值 destroy 方法,容器关闭时,销毁销毁bean 的过程中调用;
在Spring框架中,我们可以在Bean的销毁阶段插入自己的逻辑,这可以通过以下几种方式实现:

-. DisposableBean:该接口提供一个destroy方法,Spring容器在销毁bean时会调用这个方法,我们可以在这个方法中添加自定义的销毁逻辑。

-. destroy-method:在xml配置文件中使用<bean>标签定义一个bean时,可以为destroy-method属性指定一个方法名。Spring容器在销毁bean时会调用该方法。

  • @PreDestroy:在bean的一个方法上添加此注解,Spring容器在销毁bean时会调用该方法。这是一种基于注解的方式。

-. DestructionAwareBeanPostProcessor接口:装备了postProcessBeforeDestruction方法,当bean在销毁之前会调用这个方法。

总结

spring 通过BeanDefinition map 进行遍历创建bean ,在bean 的实例化之前和实例化之后可以通过 实现InstantiationAwareBeanPostProcessor接口 来进行扩展,在bean 的初始中可以通过实现 BeanPostProcessor 接口扩展初始化前和后,通过实现InitializingBean 接口扩展初始化业务,在说的bean 都完成实例化和初始化之后 实现 SmartInitializingSingleton 扩展,在容器关闭时实现 DisposableBean 接口扩展bean的销毁;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1211826.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PostGIS学习教程六:几何图形(geometry)

文章目录 一、介绍二、元数据表三、表示真实世界的对象3.1、点&#xff08;Points&#xff09;3.2、线串&#xff08;Linestring&#xff09;3.3、多边形&#xff08;Polygon&#xff09;3.4、图形集合&#xff08;Collection&#xff09; 四、几何图形输入和输出五、从文本转换…

Mysql中的索引与事务和B树的知识补充

索引与事务和B树的知识补充 一.索引1.概念2.作用3.使用场景4.使用 二.事务1.为什么使用事务2.事务的概念3.使用3.1脏读问题3.2不可重复读3.3 幻读问题3.4解决3.5 使用代码 三.B树的知识补充1.B树2.B树 一.索引 1.概念 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记…

C++基础知识记录

github仓库不定期更新: https://github.com/han-0111/CppLearning 文章目录 C如何工作编译器和链接器编译器预处理(Preprocessing)includedefineif/endif 链接器一种比较复杂的情况 变量变量类型intcharshortlonglong longfloatdoublebool如何查看数据大小 函数头文件条件语句…

使用 sCrypt CLI 工具验证合约

通过向 Whatsonchain 提交合约源代码可以实现合约的验证。 另外一种方法是使用 sCrypt CLI 工具来验证合约。 You can verify the deployed smart contracts script using the verify command: scrypt verify <scriptHash> <contractPath>第一个位置参数是已部署…

博客系统页面设计

目录 前言 1.预期效果 1.1博客列表页效果 1.2博客详情页效果 1.3博客登陆页效果 2.实现博客列表页 2.1实现导航栏 2.2实现版心 2.3实现个人信息 2.4实现博客列表 3.实现博客正文页 3.1引入导航栏 3.2引入版心 3.3引入个人信息 3.4实现博客正文 4.实现博客登陆页…

javascript原来还可以这样比较两个日期(直接使用new Date)

有个需求是这样的&#xff1a;假设今天是2023/11/15 有一个表格&#xff0c;表格中操作列按钮的展示与隐藏依靠开始结束日期来进行展示&#xff0c;如果当前日期在开始结束日期之间&#xff0c;则进行展示&#xff0c;我一开始做的时候使用new Date转换成时间戳(getTime)进行比…

7天入门python系列之爬取热门小说项目实战,互联网的东西怎么算白嫖呢

第七天 Python项目实操 编者打算开一个python 初学主题的系列文章&#xff0c;用于指导想要学习python的同学。关于文章有任何疑问都可以私信作者。对于初学者想在7天内入门Python&#xff0c;这是一个紧凑的学习计划。但并不是不可完成的。 学到第7天说明你已经对python有了一…

生活消费分销系统搭建开发制作

文章目录 前言 一、生活消费系统是什么&#xff1f;二、生活消费分销系统的营销方式和功能三、总结 一、生活消费系统介绍 生活消费系统涵盖了吃喝玩乐&#xff0c;衣食住行。网购消费等生活消费的优惠券领取以及分销功能 二、生活消费分销系统的营销方式和功能 A: 会员体…

基于Springboot的影城管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的影城管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 项目介绍…

【Proteus仿真】【Arduino单片机】DS18B20温度计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用PCF8574、LCD1602液晶、DS18B20温度传感器等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示传感器采集温度。 二、软件设计 /*…

Android抓包工具—Fiddler详解

前言 平时和其他大佬交流时&#xff0c;总会出现这么些话&#xff0c;“抓个包看看就知道哪出问题了”&#xff0c;“抓流量啊&#xff0c;payload都在里面”&#xff0c;“这数据流怎么这么奇怪”。 &#x1f449;这里出现的名词&#xff0c;其实都是差不多的意思啊&#xf…

leetcode:1576. 替换所有的问号(python3解法)

难度&#xff1a;简单 给你一个仅包含小写英文字母和 ? 字符的字符串 s&#xff0c;请你将所有的 ? 转换为若干小写字母&#xff0c;使最终的字符串不包含任何 连续重复 的字符。 注意&#xff1a;你 不能 修改非 ? 字符。 题目测试用例保证 除 ? 字符 之外&#xff0c;不存…

Unity反编译:IL2CPP 打包输出的cpp文件和dll(程序集)位置、Mono打包输出的dll(程序集)位置

目录 如题&#xff1a;IL2CPP 打包输出的cpp文件和dll位置(并不会出现在APK里) 如题&#xff1a;Mono打包输出的dll位置 校验平台&#xff1a;Android 如题&#xff1a;IL2CPP 打包输出的cpp文件和dll位置(并不会出现在APK里) Unity Assets同级目录下 Temp/StagingArea/Il2…

C# datagridView 控件使用心得

首先本人的需求是&#xff0c;通过UI编辑一个表格文件&#xff0c;然后将其存储起来。 同时也可以对其进行载入,话不多说先上图片 dataGridView1 的初始化&#xff0c;这个控件的初始化可以使用UI界面的设置&#xff0c;也可以使用程序&#xff1a; Column1 new System.Window…

开源免费的Windows应用程序强力卸载工具Bulk Crap UninstallerV5.7的简单使用

经常遇到Windows平台上安装的一些应用&#xff0c;因为应用自带的安装卸载程序有问题、应用的卸载程序损坏、应用卸载需要密码等原因&#xff0c;导致应用无法卸载、卸载不完整等。本介绍了开源的Windows应用程序强力卸载工具Bulk Crap UninstallerV5.7和安装使用的简单说明。 …

Ubuntu 搜狗输入法无法输入中文解决方案(不需要重装,不需要重启服务器)

Ubuntu 搜狗输入法突然无法输入中文&#xff0c;上午还好用&#xff0c;下午就不好用了&#xff0c;直接上解决方案 1.终端输入pidof fcitx找到搜狗的进程&#xff0c;如下图红框中的就是进程 2.直接杀掉这个进程 3.其实到第二步&#xff0c;如果搜狗输入法自动重启了&#xf…

数据库事务相关问题

1. 什么是数据库事务&#xff1f; 事务&#xff0c;由一个有限的数据库操作序列构成&#xff0c;这些操作要么全部执行,要么全部不执行&#xff0c;是一个不可分割的工作单位。 假如A转账给B 100 元&#xff0c;先从A的账户里扣除 100 元&#xff0c;再在 B 的账户上加上 100 …

力扣每日一道系列 --- LeetCode 160. 相交链表

&#x1f4f7; 江池俊&#xff1a; 个人主页 &#x1f525;个人专栏&#xff1a; ✅数据结构探索 ✅LeetCode每日一道 &#x1f305; 有航道的人&#xff0c;再渺小也不会迷途。 LeetCode 160. 相交链表 思路&#xff1a; 首先计算两个链表的长度&#xff0c;然后判断两个链…

原生js做打地鼠游戏

抱歉素材有点难找&#xff0c;这次的学习重点是在JS的实现&#xff0c;梳理一下打地鼠的实现逻辑&#xff0c;主要分为三个主要功能函数。 开始游戏&#xff1a;对分数、并根据游戏难度对游戏的倒计时和延迟进行初始化之后&#xff0c;利用setInterval定时器Math.random随机函…

淘宝客APP源码/社交电商自营商城源码/前端基于Uniapp开发

淘宝客APP源码&#xff0c;前端基于Uniapp开发的社交电商自营商城源码。Thinkphp的后台&#xff0c;不是很标准&#xff0c;感兴趣的可以自行研究。 商城功能 1、首页基础装修&#xff1b;2、丰富选品库&#xff1b;3、淘口令解析&#xff1b;4、支持京东&#xff1b;5、支持…