博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Spring源码分析】非懒加载的单例Bean初始化过程(下篇)
阅读量:6264 次
发布时间:2019-06-22

本文共 23257 字,大约阅读时间需要 77 分钟。

doCreateBean方法

上文,分析了单例的Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实例化出来的。先贴一下AbstractAutowireCapableBeanFactory的doCreateBean方法代码:

1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) { 2     // Instantiate the bean. 3     BeanWrapper instanceWrapper = null; 4     if (mbd.isSingleton()) { 5         instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); 6     } 7     if (instanceWrapper == null) { 8         instanceWrapper = createBeanInstance(beanName, mbd, args); 9     }10     final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);11     Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);12 13     // Allow post-processors to modify the merged bean definition.14     synchronized (mbd.postProcessingLock) {15         if (!mbd.postProcessed) {16             applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);17             mbd.postProcessed = true;18         }19     }20 21     // Eagerly cache singletons to be able to resolve circular references22     // even when triggered by lifecycle interfaces like BeanFactoryAware.23     boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&24             isSingletonCurrentlyInCreation(beanName));25     if (earlySingletonExposure) {26         if (logger.isDebugEnabled()) {27             logger.debug("Eagerly caching bean '" + beanName +28                     "' to allow for resolving potential circular references");29         }30         addSingletonFactory(beanName, new ObjectFactory() {31             public Object getObject() throws BeansException {32                 return getEarlyBeanReference(beanName, mbd, bean);33             }34         });35     }36 37     // Initialize the bean instance.38     Object exposedObject = bean;39     try {40         populateBean(beanName, mbd, instanceWrapper);41         if (exposedObject != null) {42             exposedObject = initializeBean(beanName, exposedObject, mbd);43         }44     }45     catch (Throwable ex) {46         if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {47             throw (BeanCreationException) ex;48         }49         else {50             throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);51         }52     }53 54     if (earlySingletonExposure) {55         Object earlySingletonReference = getSingleton(beanName, false);56         if (earlySingletonReference != null) {57             if (exposedObject == bean) {58                 exposedObject = earlySingletonReference;59             }60             else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {61                 String[] dependentBeans = getDependentBeans(beanName);62                 Set
actualDependentBeans = new LinkedHashSet
(dependentBeans.length);63 for (String dependentBean : dependentBeans) {64 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {65 actualDependentBeans.add(dependentBean);66 }67 }68 if (!actualDependentBeans.isEmpty()) {69 throw new BeanCurrentlyInCreationException(beanName,70 "Bean with name '" + beanName + "' has been injected into other beans [" +71 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +72 "] in its raw version as part of a circular reference, but has eventually been " +73 "wrapped. This means that said other beans do not use the final version of the " +74 "bean. This is often the result of over-eager type matching - consider using " +75 "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");76 }77 }78 }79 }80 81 // Register bean as disposable.82 try {83 registerDisposableBeanIfNecessary(beanName, bean, mbd);84 }85 catch (BeanDefinitionValidationException ex) {86 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);87 }88 89 return exposedObject;90 }

下面继续分析初始化一个Bean的流程,不太重要的流程就跳过了。

 

属性注入

属性注入的代码比较好找,可以看一下40行,取名为populateBean,即填充Bean的意思,看一下代码实现:

1 protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) { 2     PropertyValues pvs = mbd.getPropertyValues(); 3  4     if (bw == null) { 5         if (!pvs.isEmpty()) { 6             throw new BeanCreationException( 7                     mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); 8         } 9         else {10             // Skip property population phase for null instance.11             return;12         }13     }14 15     // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the16     // state of the bean before properties are set. This can be used, for example,17     // to support styles of field injection.18     boolean continueWithPropertyPopulation = true;19 20     if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {21         for (BeanPostProcessor bp : getBeanPostProcessors()) {22             if (bp instanceof InstantiationAwareBeanPostProcessor) {23                 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;24                 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {25                     continueWithPropertyPopulation = false;26                     break;27                 }28             }29         }30     }31 32     if (!continueWithPropertyPopulation) {33         return;34     }35 36     if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||37             mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {38         MutablePropertyValues newPvs = new MutablePropertyValues(pvs);39 40         // Add property values based on autowire by name if applicable.41         if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {42             autowireByName(beanName, mbd, bw, newPvs);43         }44 45         // Add property values based on autowire by type if applicable.46         if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {47             autowireByType(beanName, mbd, bw, newPvs);48         }49 50         pvs = newPvs;51     }52 53     boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();54     boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);55 56     if (hasInstAwareBpps || needsDepCheck) {57         PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);58         if (hasInstAwareBpps) {59             for (BeanPostProcessor bp : getBeanPostProcessors()) {60                 if (bp instanceof InstantiationAwareBeanPostProcessor) {61                     InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;62                     pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);63                     if (pvs == null) {64                         return;65                     }66                 }67             }68         }69         if (needsDepCheck) {70             checkDependencies(beanName, mbd, filteredPds, pvs);71         }72     }73 74     applyPropertyValues(beanName, mbd, bw, pvs);75 }

这段代码层次有点深,跟一下74行的applyPropertyValues方法,最后那个pvs的实现类为MutablePropertyValues,里面持有一个List<PropertyValue>,每一个PropertyValue包含了此Bean属性的属性名与属性值。74行的代码实现为:

1 protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { 2     if (pvs == null || pvs.isEmpty()) { 3         return; 4     } 5  6     MutablePropertyValues mpvs = null; 7     List
original; 8 9 if (System.getSecurityManager()!= null) {10 if (bw instanceof BeanWrapperImpl) {11 ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());12 }13 }14 15 if (pvs instanceof MutablePropertyValues) {16 mpvs = (MutablePropertyValues) pvs;17 if (mpvs.isConverted()) {18 // Shortcut: use the pre-converted values as-is.19 try {20 bw.setPropertyValues(mpvs);21 return;22 }23 catch (BeansException ex) {24 throw new BeanCreationException(25 mbd.getResourceDescription(), beanName, "Error setting property values", ex);26 }27 }28 original = mpvs.getPropertyValueList();29 }30 else {31 original = Arrays.asList(pvs.getPropertyValues());32 }33 34 TypeConverter converter = getCustomTypeConverter();35 if (converter == null) {36 converter = bw;37 }38 BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);39 40 // Create a deep copy, resolving any references for values.41 List
deepCopy = new ArrayList
(original.size());42 boolean resolveNecessary = false;43 for (PropertyValue pv : original) {44 if (pv.isConverted()) {45 deepCopy.add(pv);46 }47 else {48 String propertyName = pv.getName();49 Object originalValue = pv.getValue();50 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);51 Object convertedValue = resolvedValue;52 boolean convertible = bw.isWritableProperty(propertyName) &&53 !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);54 if (convertible) {55 convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);56 }57 // Possibly store converted value in merged bean definition,58 // in order to avoid re-conversion for every created bean instance.59 if (resolvedValue == originalValue) {60 if (convertible) {61 pv.setConvertedValue(convertedValue);62 }63 deepCopy.add(pv);64 }65 else if (convertible && originalValue instanceof TypedStringValue &&66 !((TypedStringValue) originalValue).isDynamic() &&67 !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {68 pv.setConvertedValue(convertedValue);69 deepCopy.add(pv);70 }71 else {72 resolveNecessary = true;73 deepCopy.add(new PropertyValue(pv, convertedValue));74 }75 }76 }77 if (mpvs != null && !resolveNecessary) {78 mpvs.setConverted();79 }80 81 // Set our (possibly massaged) deep copy.82 try {83 bw.setPropertyValues(new MutablePropertyValues(deepCopy));84 }85 catch (BeansException ex) {86 throw new BeanCreationException(87 mbd.getResourceDescription(), beanName, "Error setting property values", ex);88 }89 }

之后在第41行~第76行做了一次深拷贝(只是名字叫做深拷贝而已,其实就是遍历PropertyValue然后一个一个赋值到一个新的List而不是Java语义上的Clone,这里使用深拷贝是为了解析Values值中的所有引用),将PropertyValue一个一个赋值到一个新的List里面去,起名为deepCopy。最后执行83行进行复制,bw即BeanWrapper,持有Bean实例的一个Bean包装类,看一下代码实现:

1 public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) 2         throws BeansException { 3  4     List
propertyAccessExceptions = null; 5 List
propertyValues = (pvs instanceof MutablePropertyValues ? 6 ((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues())); 7 for (PropertyValue pv : propertyValues) { 8 try { 9 // This method may throw any BeansException, which won't be caught10 // here, if there is a critical failure such as no matching field.11 // We can attempt to deal only with less serious exceptions.12 setPropertyValue(pv);13 }14 catch (NotWritablePropertyException ex) {15 if (!ignoreUnknown) {16 throw ex;17 }18 // Otherwise, just ignore it and continue...19 }20 catch (NullValueInNestedPathException ex) {21 if (!ignoreInvalid) {22 throw ex;23 }24 // Otherwise, just ignore it and continue...25 }26 catch (PropertyAccessException ex) {27 if (propertyAccessExceptions == null) {28 propertyAccessExceptions = new LinkedList
();29 }30 propertyAccessExceptions.add(ex);31 }32 }33 34 // If we encountered individual exceptions, throw the composite exception.35 if (propertyAccessExceptions != null) {36 PropertyAccessException[] paeArray =37 propertyAccessExceptions.toArray(new PropertyAccessException[propertyAccessExceptions.size()]);38 throw new PropertyBatchUpdateException(paeArray);39 }40 }

这段代码没什么特别的,遍历前面的deepCopy,拿每一个PropertyValue,执行第12行的setPropertyValue:

1 public void setPropertyValue(PropertyValue pv) throws BeansException { 2     PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens; 3     if (tokens == null) { 4         String propertyName = pv.getName(); 5         BeanWrapperImpl nestedBw; 6         try { 7             nestedBw = getBeanWrapperForPropertyPath(propertyName); 8         } 9         catch (NotReadablePropertyException ex) {10             throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,11                     "Nested property in path '" + propertyName + "' does not exist", ex);12         }13         tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName));14         if (nestedBw == this) {15             pv.getOriginalPropertyValue().resolvedTokens = tokens;16         }17         nestedBw.setPropertyValue(tokens, pv);18     }19     else {20         setPropertyValue(tokens, pv);21     }22 }

找一个合适的BeanWrapper,这里就是自身,然后执行17行的setPropertyValue方法进入最后一步,方法非常长,截取核心的一段:

1 final Method writeMethod = (pd instanceof GenericTypeAwarePropertyDescriptor ? 2     ((GenericTypeAwarePropertyDescriptor) pd).getWriteMethodForActualAccess() : 3     pd.getWriteMethod()); 4     if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) { 5     if (System.getSecurityManager()!= null) { 6         AccessController.doPrivileged(new PrivilegedAction() { 7                 public Object run() { 8                     writeMethod.setAccessible(true); 9                     return null;10                 }11             });12         }13         else {14             writeMethod.setAccessible(true);15         }16     }17     final Object value = valueToApply;18     if (System.getSecurityManager() != null) {19     try {20         AccessController.doPrivileged(new PrivilegedExceptionAction() {21             public Object run() throws Exception {22                 writeMethod.invoke(object, value);23                 return null;24             }25         }, acc);26     }27     catch (PrivilegedActionException ex) {28         throw ex.getException();29     }30 }31 else {32     writeMethod.invoke(this.object, value);33 }

大致流程就是两步:

(1)拿到写方法并将方法的可见性设置为true

(2)拿到Value值,对Bean通过反射调用写方法

这样完成了对于Bean属性值的设置。

 

Aware注入

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

1 protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { 2     if (System.getSecurityManager() != null) { 3         AccessController.doPrivileged(new PrivilegedAction() { 4             public Object run() { 5                 invokeAwareMethods(beanName, bean); 6                 return null; 7             } 8         }, getAccessControlContext()); 9     }10     else {11         invokeAwareMethods(beanName, bean);12     }13         14     Object wrappedBean = bean;15     if (mbd == null || !mbd.isSynthetic()) {16         wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);17     }18 19     try {20         invokeInitMethods(beanName, wrappedBean, mbd);21     }22     catch (Throwable ex) {23         throw new BeanCreationException(24                 (mbd != null ? mbd.getResourceDescription() : null),25                 beanName, "Invocation of init method failed", ex);26     }27 28     if (mbd == null || !mbd.isSynthetic()) {29         wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);30     }31     return wrappedBean;32 }

看一下上面第5行的实现:

1 private void invokeAwareMethods(final String beanName, final Object bean) { 2     if (bean instanceof BeanNameAware) { 3         ((BeanNameAware) bean).setBeanName(beanName); 4     } 5     if (bean instanceof BeanClassLoaderAware) { 6         ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader()); 7     } 8     if (bean instanceof BeanFactoryAware) { 9         ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);10     }11 }

看到这里判断,如果bean是BeanNameAware接口的实现类会调用setBeanName方法、如果bean是BeanClassLoaderAware接口的实现类会调用setBeanClassLoader方法、如果是BeanFactoryAware接口的实现类会调用setBeanFactory方法,注入对应的属性值。

 

调用BeanPostProcessor的postProcessBeforeInitialization方法

上面initializeBean方法再看16行其实现:

1 public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) 2         throws BeansException { 3  4     Object result = existingBean; 5     for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { 6         result = beanProcessor.postProcessBeforeInitialization(result, beanName); 7         if (result == null) { 8             return result; 9         }10     }11     return result;12 }

遍历每个BeanPostProcessor接口实现,调用postProcessBeforeInitialization方法,这个接口的调用时机之后会总结,这里就代码先简单提一下。

 

调用初始化方法

initializeBean方法的20行,调用Bean的初始化方法,看一下实现:

1 protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) 2         throws Throwable { 3  4     boolean isInitializingBean = (bean instanceof InitializingBean); 5     if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { 6         if (logger.isDebugEnabled()) { 7             logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); 8         } 9         if (System.getSecurityManager() != null) {10             try {11                 AccessController.doPrivileged(new PrivilegedExceptionAction() {12                     public Object run() throws Exception {13                         ((InitializingBean) bean).afterPropertiesSet();14                         return null;15                     }16                 }, getAccessControlContext());17             }18             catch (PrivilegedActionException pae) {19                 throw pae.getException();20             }21         }                22         else {23             ((InitializingBean) bean).afterPropertiesSet();24         }25     }26 27     if (mbd != null) {28         String initMethodName = mbd.getInitMethodName();29         if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&30                     !mbd.isExternallyManagedInitMethod(initMethodName)) {31             invokeCustomInitMethod(beanName, bean, mbd);32         }33     }34 }

看到,代码做了两件事情:

1、先判断Bean是否InitializingBean的实现类,是的话,将Bean强转为InitializingBean,直接调用afterPropertiesSet()方法

2、尝试去拿init-method,假如有的话,通过反射,调用initMethod

因此,两种方法各有优劣:使用实现InitializingBean接口的方式效率更高一点,因为init-method方法是通过反射进行调用的;从另外一个角度讲,使用init-method方法之后和Spring的耦合度会更低一点。具体使用哪种方式调用初始化方法,看个人喜好。

 

调用BeanPostProcessor的postProcessAfterInitialization方法

最后一步,initializeBean方法的29行:

1 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) 2         throws BeansException { 3  4     Object result = existingBean; 5     for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { 6         result = beanProcessor.postProcessAfterInitialization(result, beanName); 7         if (result == null) { 8             return result; 9         }10     }11     return result;12 }

同样遍历BeanPostProcessor,调用postProcessAfterInitialization方法。因此对于BeanPostProcessor方法总结一下:

1、在初始化每一个Bean的时候都会调用每一个配置的BeanPostProcessor的方法

2、在Bean属性设置、Aware设置后调用postProcessBeforeInitialization方法

3、在初始化方法调用后调用postProcessAfterInitialization方法

 

注册需要执行销毁方法的Bean

接下来看一下最上面doCreateBean方法的第83行registerDisposableBeanIfNecessary(beanName, bean, mbd)这一句,完成了创建Bean的最后一件事情:注册需要执行销毁方法的Bean。

看一下方法的实现:

1 protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) { 2     AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null); 3     if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) { 4         if (mbd.isSingleton()) { 5             // Register a DisposableBean implementation that performs all destruction 6             // work for the given bean: DestructionAwareBeanPostProcessors, 7             // DisposableBean interface, custom destroy method. 8             registerDisposableBean(beanName, 9                     new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));10         }11         else {12             // A bean with a custom scope...13             Scope scope = this.scopes.get(mbd.getScope());14             if (scope == null) {15                 throw new IllegalStateException("No Scope registered for scope '" + mbd.getScope() + "'");16             }17             scope.registerDestructionCallback(beanName,18                     new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));19         }20     }21 }

其中第3行第一个判断为必须不是prototype(原型)的,第二个判断requiresDestruction方法的实现为:

1 protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {2     return (bean != null &&3             (bean instanceof DisposableBean || mbd.getDestroyMethodName() != null ||4                     hasDestructionAwareBeanPostProcessors()));5 }

要注册销毁方法,Bean需要至少满足以下三个条件之一:

(1)Bean是DisposableBean的实现类,此时执行DisposableBean的接口方法destroy()

(2)Bean标签中有配置destroy-method属性,此时执行destroy-method配置指定的方法

(3)当前Bean对应的BeanFactory中持有DestructionAwareBeanPostProcessor接口的实现类,此时执行DestructionAwareBeanPostProcessor的接口方法postProcessBeforeDestruction

在满足上面三个条件之一的情况下,容器便会注册销毁该Bean,注册Bean的方法很简单,见registerDisposableBean方法实现:

1 public void registerDisposableBean(String beanName, DisposableBean bean) {2     synchronized (this.disposableBeans) {3         this.disposableBeans.put(beanName, bean);4     }5 }

容器销毁的时候,会遍历disposableBeans,逐一执行销毁方法。

 

流程总结

本文和上篇文章分析了Spring Bean初始化的步骤,最后用一幅图总结一下Spring Bean初始化的流程:

图只是起梳理流程作用,抛砖引玉,具体代码实现还需要网友朋友们照着代码自己去一步一步分析。

转载地址:http://ifdpa.baihongyu.com/

你可能感兴趣的文章
静态代码块在何时调用
查看>>
Kafka控制器选举流程剖析
查看>>
appium封装显示等待Wait类和ExpectedCondition接口
查看>>
Android 全局弹出版本更新 Dialog 思考和解决办法
查看>>
IDEA在当前类中查找方法快捷键--转
查看>>
初识少儿编程
查看>>
浏览器 UA 判断
查看>>
理解OAuth 2.0
查看>>
高并发处理思路与手段(三):消息队列
查看>>
Docker+Nginx部署Angular
查看>>
Docker & ASP.NET Core (4):容器间的连接
查看>>
beam 的异常处理 Error Handling Elements in Apache Beam Pipelines
查看>>
将png图片转换为字体图标
查看>>
/var/log/wtmp
查看>>
C# 获取机器码
查看>>
什么是医嘱?医嘱的书写内容?
查看>>
如何通过CSP编程卸载Windows Mobile应用程序
查看>>
用delphi实现完美屏幕截图
查看>>
matlab练习程序(差异演化DE)
查看>>
这就是搜索引擎:核心技术详解
查看>>