优秀的编程知识分享平台

网站首页 > 技术文章 正文

「Spring源码分析」非懒加载的单例Bean初始化过程(下篇)

nanyue 2024-09-07 16:43:38 技术文章 7 ℃

doCreateBean方法

上文【Spring源码分析】非懒加载的单例Bean初始化过程(上篇),分析了单例的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 references
22 // 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<String> actualDependentBeans = new LinkedHashSet<String>(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 the
16 // 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<PropertyValue> 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<PropertyValue> deepCopy = new ArrayList<PropertyValue>(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<PropertyAccessException> propertyAccessExceptions = null;
 5 List<PropertyValue> 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 caught
10 // 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<PropertyAccessException>();
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<Object>() {
 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<Object>() {
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<Object>() {
 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<Object>() {
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初始化的流程:

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

最近发表
标签列表