今日播报!【Spring源码】- 03 Spring IoC容器启动之Bean创建流程
上篇已经分析完refresh()
中大部分方法,也已经把Bean
解析成BeanDefinition
注册到IoC
容器中,refresh
还剩下一个非常重要的方法,就是下面将要分析的:finishBeanFactoryInitialization
,用以完成Bean
创建、依赖注入和初始化等工作。
(资料图片仅供参考)
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // 初始化类型转换器 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)); } // 占位符表达式解析器,比如解析@Value("${test.name}") if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } // 初始化LoadTimeWeaverAware Bean,getBean则是让实现LoadTimeWeaverAware的对象提前实例化 String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } //停止使用临时的类加载器 beanFactory.setTempClassLoader(null); // 冻结所有的BeanDefinition定义,不期望以后会被修改或进一步处理,因为马上要创建Bean实例对象了 beanFactory.freezeConfiguration(); // 实例化所有的non-lazy-init 单例 beanFactory.preInstantiateSingletons();}
关键代码是最后一句:beanFactory.preInstantiateSingletons()
。
preInstantiateSingletons
@Overridepublic void preInstantiateSingletons() throws BeansException { // 获取到所有BeanDefinition名称,后面用于遍历处理 List beanNames = new ArrayList<>(this.beanDefinitionNames); // 遍历触发每个BeanDefinition实例化 for (String beanName : beanNames) { //getMergedLocalBeanDefinition()可以简单理解成获取BeanDefinition即可 //主要涉及到将其它类型的BeanDefinition统一转成成RootBeanDefinition或继承关系导致的多个BeanDefinition合并成一个 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); /** * 作用域是singleton,且不是abstract和lazy-init,才会执行初始化 * 只有singleton的Bean才会提前实例化好,其它作用域和lazy属性的Bean都是在使用时调用getBean()方法时才会被创建 */ if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { /** * 是否为FactoryBean,不是的话直接getBean(beanName),也就是实例化 * 如果是FactoryBean,走IF语句块 */ 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) ((SmartFactoryBean>) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } } else { //非FactoryBean实例化 getBean(beanName); } } } /** * 这里出现了另一个扩展点:SmartInitializingSingleton,用于所有Singleton实例创建全部完成(包括各种依赖注入、初始化等)后, * 去执行SmartInitializingSingleton#afterSingletonsInstantiated回调方法 */ for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); // 如果实例实现了SmartInitializingSingleton,执行afterSingletonsInstantiated方法。 if (singletonInstance instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction
非FactoryBean
创建走的是getBean()
,内部又会委托给doGetBean()
方法。
注意,这里出现了另一个重要的扩展点:SmartInitializingSingleton#afterSingletonsInstantiated
,从代码上看就是所有非Lazy类型的Singleton实例都被全部创建完成后,会触发回调。案例可参见EventListenerMethodProcessor
:待所有Singleton
创建完毕,找到其中标注了@EventListener
注解的方法,利用反射和DefaultEventListenerFactory
为其创建ApplicationListener
,并添加到事件派发器的缓存中。
doGetBean
protected T doGetBean(final String name, @Nullable final Class requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { //解析beanName,主要是解析别名、去掉FactoryBean的前缀“&” final String beanName = transformedBeanName(name); Object bean; /** * 通过singletonObjects()方法先尝试从缓存中获取bean实例,获取不到再走后面创建的流程,通过缓存解决循环依赖问题 * * 获取到有两种情况: * 一种是Bean创建完成后,会存储到该缓存中 * 另一种是未创建完成,但先预存到一个单独的缓存中,这种是针对可能存在循环引用的情况的处理。 * 如A引用B,B又引用了A,因而在初始化A时,A会先调用构造函数创建出一个实例,在依赖注入B之前,现将A实例缓存起来 * 然后在初始化A时,依赖注入阶段,会触发初始化B,B创建后需要依赖注入A时,先从缓存中获取A(这个时候的A是不完整的),避免循环依赖的问题出现。 */ Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { /** * 这里主要处理实现了FactoryBean的情况,需要调用重写的getObject()方法来获取实际的Bean实例。 * 普通Bean会直接返回sharedInstance本身 * preInstantiateSingletons方法中也有处理FactoryBean分支,但是那是针对Singleton且提前实例化情况, * 对于Lazy类型的FactoryBean,那个流程是走不到的,而是在getBean时才会创建,所以这里还要处理FactoryBean */ bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } //缓存没有则创建 else { //原型对象不允许循环创建,如果是原型对象则抛异常 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } /** * BeanFactory也存在继承关系,如果当前BeanFactory中找不到BeanDefinition,则到parentBeanFactory容器中找,递归向上查找 */ BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType != null) { return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } } // typeCheckOnly=true表示调用这个方法只是做类型检查,不会去做真正对象创建,正常情况下typeCheckOnly=false if (!typeCheckOnly) { //如果不是仅仅做类型检测,而是需要创建bean实例,这里要将beanName放到alreadyCreated缓存,进行已创建标记 markBeanAsCreated(beanName); } try { // 根据名字获取合并过的对应的RootBeanDefinition final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 检查mbd是否为抽象的或mbd为单例,但存在args的情况(args只有初始化原型对象才允许存在) checkMergedBeanDefinition(mbd, beanName, args); /** * 拿到当前bean依赖的bean名称集合,如使用@DependsOn,在实例化自己之前,保证依赖的这些Bean全部被初始化,递归getBean */ String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { registerDependentBean(dep, beanName); // 先实例化@DependsOn中的bd getBean(dep); } } if (mbd.isSingleton()) {//创建单例Bean // 会先尝试从缓存中获取,获取失败就通过ObjectFactory的createBean方法创建 sharedInstance = getSingleton(beanName, () -> { try { // 创建单例对象 return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } }); //这里主要处理实现了FactoryBean的情况,需要调用重写的getObject()方法来获取实际的Bean实例。 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) {//创建多例Bean ...//省略 } else {//创建其它作用域的Bean ...//省略 } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } // 检查是否为要求的类型,如果不是则尝试进行类型转换 if (requiredType != null && !requiredType.isInstance(bean)) { ...//省略 } return (T) bean;}
createBean()
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { ...//省略 /** * 实例化前的处理,如果有实现InstantiationAwareBeanPostProcessor的BeanPostProcessor可以直接返回真正的bean实例 * 然后依次所有注册的BeanPostProcessor的postProcessAfterInitialization方法(同样如果任意一次返回不为null,即终止调用。 */ Object bean = resolveBeforeInstantiation(beanName, mbdToUse); // 如果不为空,说明提前生成了实例,直接返回 if (bean != null) { return bean; } ...//省略 //创建Bean实例(一般真正创建Bean的方法) Object beanInstance = doCreateBean(beanName, mbdToUse, args); return beanInstance;}
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
这句代码比较关键,这里有个关键的扩展点回调:触发InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()
方法执行。postProcessBeforeInstantiation()
这个方法在创建Bean
之前执行,可能会存在多个InstantiationAwareBeanPostProcessor
,按照注册顺序一个个执行回调,如果其中有一个返回非null
,则终止后续回调,然后直接调用BeanPostProcessor#postProcessAfterInitialization
(Bean
初始化完成回调接口),则表示整个Bean
全部初始化完成,直接返回。依赖注入、init-method
方法等都会被忽略执行。
如果InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
都返回null
,则表示需要继续往下通过常规方式doCreateBean()
方法创建Bean
实例。
doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Initialize the bean instance. // 开始对Bean实例进行初始化,依赖注入在这里发生,exposedObject 在初始化处理完后会返回作为依赖注入完成后的Bean Object exposedObject = bean;//这里还是原生对象 try { /** populateBean(beanName, mbd, instanceWrapper); /** * 完成属性依赖注入后,进一步初始化Bean,具体进行了以下操作: * 1.若实现了BeanNameAware, BeanClassLoaderAware,BeanFactoryAwareAware等接口,则注入相关对象 * 2.遍历后置处理器,调用实现的postProcessBeforeInitialization方法, * 3.如果实现了InitialzingBean,调用实现的 afterPropertiesSet() * 4.如果配置了init-mothod,调用相应的init方法 * 5.遍历后置处理器,调用实现的postProcessAfterInitialization * * initializeBean方法执行bean的初始化方法 * 经过AOP处理,原生对象转换成了代理对象 * 执行后置处理器,aop就是在这里完成的处理 */ 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 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. try { // 如果实现了Disposable接口,会在这里进行注册,最后在销毁的时候调用相应的destroy方法 registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }
doCreateBean
是比较关键的一个方法,Spring
中doXXX
这种开头的基本都是真正干活的。这个方法完成的业务逻辑比较多,下面我们把这个方法拆解下分析。
createBeanInstance
createBeanInstance(beanName, mbd, args)
这个方法是真正使用策略创建Bean实例,并返回包装类BeanWrapper
,大部分情况就是调用无参构造方法通过反射创建对象,但是Spring要考虑各种情况,所以这个类设计的比较复杂。BeanWrapper
是对创建的Bean
进行了一层包装,主要是方便对Bean
中各种属性进行操作。
MergedBeanDefinitionPostProcessor回调
执行MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
回调,这个扩展点主要用来解析注解信息,然后缓存起来供后续处理使用。比如:AutowiredAnnotationBeanPostProcessor
、CommonAnnotationBeanPostProcessor
等实现类都是在这个方法中把相应的注解信息解析缓存到集合中,比如@Autowired
、@Value
、@Resource
,为后续实现依赖注入准备基础信息。
synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { //获取所有实现MergedBeanDefinitionPostProcessor接口的后置处理器,调用其postProcessMergedBeanDefinition方法 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; }}
提前暴露Bean,防止循环依赖
这时的Bean
刚被创建完成,但是还没有依赖注入、initMethod
等方法初始化,把Bean
包装到ObjectFactory
中放到缓存Map
中提前暴露出去,解决循环依赖问题。
// 提前将Bean暴露到IoC容器中,用于解决循环依赖boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean "" + beanName + "" to allow for resolving potential circular references"); } /** * 提前暴露beanName的ObjectFactory,用于解决循环引用,确保其他Bean能引用到此bean * * 其实就是调用singletonFactories.put(beanName, singletonFactory)将ObjectFactory存储到Map中 * * A引用B,同时B也引用A * 1、在初始化A过程中执行到这里时,由于还没有初始化完成,所以会将A包装成一个ObjectFactory提前暴露出去; * 2、初始化A继续向下执行,当执行到populate进行依赖注入时,发现需要对象B,这时就getBean(B)递归进入到创建B的流程里面去了; * 3、B初始化过程中,也执行到了populate方法进行依赖注入时,需要getBean(A)获取对象A进行依赖注入; * 4、getBean(A)过程中首先getSingleton()从缓存中获取,getSingleton()就可以获取到提前暴露的A对应的ObjectFactory对象; * 5、然后调用ObjectFactory.getObject(),进而调用getEarlyBeanReference() * 6、getEarlyBeanReference()方法会触发一个扩展点:SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference如果返回非null,则可以覆盖当前bean */ addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}
当存在循环依赖时,调用getEarlyBeanReference()
获取依赖值时,主要注意这里面存在一个扩展点:SmartInstantiationAwareBeanPostProcessor
。
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { Object exposedObject = bean; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); } } } return exposedObject;}
循环依赖情况下,注入还未完全初始化完成的Bean时,这时就会通过getEarlyBeanReference()
获取依赖值。这时会调用SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference
,如果有返回值则会覆盖掉之前初始化的Bean
进行注入。
populateBean
populateBean
方法完成依赖注入任务,主要包括三种方式的依赖注入:自动注入、注解注入和PropertyValues
注入。
1、回调InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
方法,Bean
创建之后,依赖注入之前执行,最后一次机会在属性注入前修改Bean
的属性值,比如修改属性值、修改属性依赖的beanName
等等。postProcessAfterInstantiation()
方法有个boolean
返回值,一般都是返回true
;如果返回false
,则表示不必继续进行依赖注入,立即停止后续的postProcessAfterInstantiation
方法执行,并跳出populateBean
方法执行。
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { /** * InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation:Bean创建之后,依赖注入之前执行,最后一次机会在属性注入前修改Bean的属性值 * postProcessAfterInstantiation()一般都是返回true, * 如果返回false,则表示不必继续进行依赖注入,立即停止后续的postProcessAfterInstantiation方法执行,并跳出populateBean方法执行。 */ if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } }}
2、自动注入方式,该方式在实际开发中使用比较少,简单了解下即可,通过下面代码解析出自动注入所需的PropertyValues
对象,最后执行applyPropertyValues(beanName, mbd, bw, pvs);
完成依赖注入工作。
/*** Spring内部可以对BeanDefinition进行设置值, 参照自定义的 BeanFactory中获取到BeanDefinition.getPropertyValue().addXXX();* pvs是一个MutablePropertyValues实例,里面存储PropertyValue集合,通过PropertyValue实现对属性的赋值、依赖注入*/PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);/*** 自动注入方式:byName还是byType,依赖注入方式:如果设置了相关的依赖装配方式,会遍历Bean中的属性,根据类型或名称来完成相应注入,无需额外配置* @Autowired注解默认是AUTOWIRE_NO=0,即不走以下逻辑*/int resolvedAutowireMode = mbd.getResolvedAutowireMode();if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { // 深拷贝当前已有的配置 MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // 自动根据名称注入 if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // 自动根据类型注入 if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } //组合需要依赖注入配置数据 pvs = newPvs;}
BeanDefinitionDefaults
类autowireMode
属性配置,BeanDefinition
相关的全局配置都可以通过这个类设置:
public class BeanDefinitionDefaults { private Boolean lazyInit; private int autowireMode = AbstractBeanDefinition.AUTOWIRE_NO; private int dependencyCheck = AbstractBeanDefinition.DEPENDENCY_CHECK_NONE; private String initMethodName; private String destroyMethodName;}
ClassPathBeanDefinitionScanner#setBeanDefinitionDefaults
可以配置该类,这样scanner
扫描生成BeanDefinition
时就会应用到该配置信息。
3、@Autowired
、@Value
、@Resource
等注解方式实现的依赖注入;
PropertyDescriptor[] filteredPds = null;if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } /** * 回调InstantiationAwareBeanPostProcessor#postProcessProperties方法 * AutowiredAnnotationBeanPostProcessor,就是在这个方法中完成@Autowired、@Value注解的依赖注入 * CommonAnnotationBeanPostProcessor:支持JSR-250的一些注解,如:@Resource、@PostConstruct、@PreDestroy等 */ for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { //获取出对象的所有set get方法,现在是有一个 getClass()方法,因为继承了Object, 没什么其他卵用 filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } //postProcessPropertyValues方法已废弃,被postProcessProperties替代 pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } }}
注解方式实现的依赖注入主要借助于MergedBeanDefinitionPostProcessor
和InstantiationAwareBeanPostProcessor
这两类扩展类实现。比如@Autowired
、@Value
依赖注入的实现类是AutowiredAnnotationBeanPostProcessor
,以及@Resource等JSR-250相关依赖注入的实实现类是CommonAnnotationBeanPostProcessor
,他们都实现了MergedBeanDefinitionPostProcessor
和InstantiationAwareBeanPostProcessor
这两个接口。一般是在MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
方法中完成注解信息解析,然后缓存到Map
等集合中,在InstantiationAwareBeanPostProcessor#postProcessProperties
回调方法中,从缓存中查找依赖注入信息,然后进行依赖注入。
4、最后完成PropertyValues
的依赖注入
if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs);}
PropertyValues
的依赖注入主要有两个来源:一种就是上面自动注入解析出来的PropertyValue
;另一种就是自己通过BeanDefinition#addPropertyValue
方法设置,比如:
BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(User.class);//注入指定值bdb.addPropertyValue("name", "张三");//注入一个引用值,第二个参数指定beanName,依赖注入时从IoC查找到beanName对应的Bean进行注入bdb.addPropertyReference("friend", "user03");beanDefinitionRegistry.registerBeanDefinition("user", bdb.getBeanDefinition());
initializeBean
initializeBean()
这个方法主要完成Bean的初始化工作,以及在初始化前后都存在BeanPostProcessor
扩展点进行方法回调。
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction
这里注意点是存在三种方式触发initMethod
:
@PostConstruct
这种比较常用的注解方式,是在InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization
方法中被调用的,所以它执行时机是最早的;实现InitializingBean
这种方式次之,具体见invokeInitMethods
方法;最后执行的是@Bean(initMethod = "xxx")
这种方式配置的initMethod
;protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { //实现InitializingBean,则调用afterPropertiesSet()方法 boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { ((InitializingBean) bean).afterPropertiesSet(); ...//省略 } /** * 执行BeanDefinition中设置到initMethodName的初始化方法, * 在ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethod()方法中会解析@Bean注解上的initMethod设置进来 */ if (mbd != null && bean.getClass() != NullBean.class) { String initMethodName = mbd.getInitMethodName(); if (StringUtils.hasLength(initMethodName) && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { invokeCustomInitMethod(beanName, bean, mbd); } }}
关键词:
-
今日播报!【Spring源码】- 03 Spring IoC容器启动之Bean创建流程
2023-03-28 -
《动物派对》通过ESRB评级登微博热搜 玩家:等太久 都不爱了|环球报道
2023-03-28 -
每日短讯:“国寿乐盈一生终身寿险(尊享版)”产品推介会在厦门举办
2023-03-28 -
世界今日讯!拖欠工资的退休仪式!梅西的哥哥透露了球王的下落,拉波尔塔可能会偷偷做坏事
2023-03-28 -
2023年清明节沧州群众祭扫工作的通告 焦点观察
2023-03-28 -
亏本秒杀!39.9元抢大牌防晒衣,上身就像穿着隐形“空调”,质量超好
2023-03-28 -
苹果watchOS 9.4正式版发布 支持直接删除内置App
2023-03-28 -
当前视点!人工流产后出血几天_人工流产手术后15天出血正常吗
2023-03-28 -
今日热议:生物股份(600201):3月27日北向资金增持41.23万股
2023-03-28 -
速讯:常用网络命令实验报告_常用网络命令
2023-03-28 -
世界快看点丨向上级单位汇报工作报告范文(优选4篇)
2023-03-27 -
夜游宫记梦寄师伯浑表达了什么情感(夜游宫记梦寄师伯浑阅读答案)
2023-03-27 -
环球要闻:BIG精神第五期 | 让百年建筑留存城市记忆
2023-03-27 -
世界微动态丨马上评|以地方立法护航“国民小吃”产业发展
2023-03-27 -
全球关注:暗黑破坏神 4 延迟高 / 卡顿 / 掉线 / 丢包 / 进不去游戏解决方法
2023-03-27 -
基金市场有一二级之分吗?—级市场和二级市场有什么区别?-天天新消息
2023-03-27 -
每日播报!和讯个股快报:2023年03月27日 金财互联(002530)该股换手率大于8%
2023-03-27 -
2023年“科技专家辽源行” 暨“人才助企”专项服务行动开展_百事通
2023-03-27 -
环球观速讯丨银行业危机主导“疯狂三月”!本周市场恐再迎动荡一周
2023-03-27 -
焦点热门:鼠年男孩最合适的名字_适合鼠年出生的男孩名字
2023-03-27 -
环球热门:中国《核安全公约》履约情况获高度肯定
2023-03-27 -
世界百事通!为婚礼做医美 她们说自我感受比排场重要
2023-03-27 -
厦门市气象台发布“海上大风预警 Ⅳ 级”
2023-03-27 -
乳腺的“一生”|全球今亮点
2023-03-26 -
海滨街道诚信社区开展“共建消防安全”知识讲座活动
2023-03-26 -
全球信息:陪审员的职责_陪审员的职责是什么
2023-03-26 -
华为手机截图怎么截长图_qq怎么截图手机
2023-03-26 -
每日速读!微信如何群发消息但不建群
2023-03-26 -
光缆线路巡检_线路巡检
2023-03-26 -
全国文物行业职业技能大赛开赛
2023-03-26
-
守住网络直播的伦理底线
2021-12-16 -
石窟寺文化需要基于保护的“新开发”
2021-12-16 -
电影工作者不能远离生活
2021-12-16 -
提升隧道安全管控能力 智慧高速让司乘安心
2021-12-16 -
人民财评:提升消费体验,服务同样重要
2021-12-16 -
卫冕?突破?旗手?——武大靖留给北京冬奥会三大悬念
2021-12-16 -
新能源车险专属条款出台“三电”系统、起火燃烧等都可保
2021-12-16 -
美术作品中的党史 | 第97集《窗外》
2021-12-16 -
基金销售业务违规!浦发银行厦门分行等被厦门证监局责令改正
2021-12-16 -
保持稳定发展有支撑——从11月“成绩单”看中国经济走势
2021-12-16