spring一個bean的容器,它從這個最基本的功能進而擴展出AOP,transaction,cache,schedule,data等等,將業務與框架代碼解耦,讓我們可以將大部分精力投入到業務代碼中,這是一個偉大的開源項目,帶着這份感激與贊美之情,來看一spring最基本的功能--bean的裝載:
我們知道,spring在1與2時使用xml等配置文件來配置bean的聲明,而3以后,spring則引入注解,大大簡化了bean的繁雜的配置,bean的裝載部分並沒有發生本質上的變化,只是稍稍做了一些改動。
如何讀取bean,這部分在本篇不打算詳細介紹。簡單說明一下流程:spring獲取bean信息(具體是配置文件還是注解按具體場景決定),將bean信息賦予BeanDefifition,這個類是關鍵,它承載了bean的所有信息。
在拿到BeanDefinition后,spring便開始裝載之旅,spring將bean的裝載划分為幾個步驟:1.裝載前,2.賦值前,3.賦值后.4.裝載后,基於這些步驟,spring均預留了相應的接口,供外部邏輯參與到bean的裝載過程中.
首先看下AbstractAutowireCapableBeanFactory.java的doCreateBean方法
// Initialize the bean instance. Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { 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); } }
主要看上面這部分代碼,一個是populateBean,一個是initializeBean,這兩個方法完成了bean的賦值與初始化。先看populateBean:
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } if (!continueWithPropertyPopulation) { return; } if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw); if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } } applyPropertyValues(beanName, mbd, bw, pvs);
populateBean做了這樣幾件事情:調用實現了InstantiationAwareBeanPostProcessor接口的postProcessAfterInstantiation方法,確認bean的賦值是否繼續,調用postProcessPropertyValues方法來確保依賴已經解析完畢,並且可以替換property的value.做完這些操作后,就可以開始賦值了.
到此,我們發現並沒有發生真正的賦值,真正的賦值邏輯在 applyPropertyValuesf方法中:
if (pvs instanceof MutablePropertyValues) { mpvs = (MutablePropertyValues) pvs; if (mpvs.isConverted()) { // Shortcut: use the pre-converted values as-is. try { bw.setPropertyValues(mpvs); return; } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } } original = mpvs.getPropertyValueList(); } else { original = Arrays.asList(pvs.getPropertyValues()); } TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); // Create a deep copy, resolving any references for values. List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size()); boolean resolveNecessary = false; for (PropertyValue pv : original) { if (pv.isConverted()) { deepCopy.add(pv); } else { String propertyName = pv.getName(); Object originalValue = pv.getValue(); Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); Object convertedValue = resolvedValue; boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); if (convertible) { convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); } // Possibly store converted value in merged bean definition, // in order to avoid re-conversion for every created bean instance. if (resolvedValue == originalValue) { if (convertible) { pv.setConvertedValue(convertedValue); } deepCopy.add(pv); } else if (convertible && originalValue instanceof TypedStringValue && !((TypedStringValue) originalValue).isDynamic() && !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) { pv.setConvertedValue(convertedValue); deepCopy.add(pv); } else { resolveNecessary = true; deepCopy.add(new PropertyValue(pv, convertedValue)); } } } if (mpvs != null && !resolveNecessary) { mpvs.setConverted(); } // Set our (possibly massaged) deep copy. try { bw.setPropertyValues(new MutablePropertyValues(deepCopy)); } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); }
這里有一個BeanDefinitionValueResolver,這個類用來解析property里的value,如果是依賴其他bean則會到容器中找是否存在如果有則返回,沒有則創建一個。spring又為每個對象的屬性定義了一個數據結構:PropertyValue,這樣做加大了容器對bean屬性的修改的靈活性,上面的方法就是對每個屬性進行處理然后通過beanWapper的setPropertyValues進行賦值。
這里注意一下,bean有singleton和prototype兩種 ,對於prototype,spring采用了原型模式,使用對象的deepcopy。
至此,spring完成了對實例的賦值,然后就是調用initializeBean:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { invokeAwareMethods(beanName, bean); return null; } }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
這里有四個重要的方法.
invokeAwareMethods
applyBeanPostProcessorsBeforeInitialization
invokeInitMethods
applyBeanPostProcessorsAfterInitialization
使用spring,就一定會知道spring有一系列aware,比如(beanNameAware,beanFactoryAware,aplicationContextArware,enviromentAware等等)。這些aware使得代碼與spring框架耦合,帶來的好處就是能讓代碼使用spring框架提供的強大功能,我們看到,在initializeBean方法中,一開始就調用了invokeAwareMethods:
private void invokeAwareMethods(final String beanName, final Object bean) { if (bean instanceof Aware) { if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } if (bean instanceof BeanClassLoaderAware) { ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader()); } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } }
這些aware發生在對象被賦值以后,在bean創建的過程中我們只看到了被調用的3個Aware方法,事實上這3個Aware方法我們用的並不多,這是因為我們常用的容器實際上是更上層的applicationContext,那么applicationContext容器的aware實在何時被調用的呢,我們會在下面的講解中展示給大家.
接下來,調用了applyBeanPostProcessorsBeforeInitialization方法:
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessBeforeInitialization(result, beanName); if (result == null) { return result; } } return result; }
我們看到,這里開始調用所有注冊了BeanPostProcessor的postProcessBeforeInitialization方法,這個方法的實現類列表中,我們看到了aop的身影,aop就是從這里開始參與進來的。
前面提到過applicationContext級別的Awaref方法的調用,沒錯,就是在這里.看一下這個類:ApplicationContextAwareProcessor它實現了BeanPostProcessor接口
這個是專門處理ApplicationContextAware相關的接口的調用的:
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException { AccessControlContext acc = null; if (System.getSecurityManager() != null && (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) { acc = this.applicationContext.getBeanFactory().getAccessControlContext(); } if (acc != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareInterfaces(bean); return null; }, acc); } else { invokeAwareInterfaces(bean); } return bean; }
private void invokeAwareInterfaces(Object bean) { if (bean instanceof Aware) { if (bean instanceof EnvironmentAware) { ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) { ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware) bean).setMessageSource(this.applicationContext); } if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } } }
這個類會在spring的refresh方法被調用的時候被創建出來,至於refresh方法何時被調用就不是本篇的重點了
上面說過,還有一個重要的方法:invokeInitMethods,從字面上可以看出,這是調用bean的初始化方法
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isDebugEnabled()) { logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { public Object run() throws Exception { ((InitializingBean) bean).afterPropertiesSet(); return null; } }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { ((InitializingBean) bean).afterPropertiesSet(); } } if (mbd != null) { String initMethodName = mbd.getInitMethodName(); if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { invokeCustomInitMethod(beanName, bean, mbd); } } }
看了這個實現,發現,原來偉大的spring也會在代碼里存在硬編碼,沒錯,這就是調用實現了InitializingBean的類的afterPropertiesSet方法,只不過之前做了一系列校驗
最后再調用applyBeanPostProcessorsAfterInitialization方法,同樣上面一樣,循環遍歷調用注冊了beanPostProcessor的方法,最后返回一個處理完成的bean實例,注意了,spring aop就是在此介入的,有興趣的同學可以看一下我的另一篇博客spring @EnableAspectJAutoProxy背后的那些事(spring AOP源碼賞析),至此,一個完成的bean的裝載過程已經完成。
@Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { Object current = beanProcessor.postProcessAfterInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
總結一下,我們經常用到的(可能用到的)一些f方法被調用的順序:
beanFactoryArware這是最底層的了
EnvironmentAware
ResourceLoaderAware
ApplicationEventPublisherAware
ApplicationContextAware
afterPropertiesSet
以上是我個人理解,因技術尚有不足,理解有誤地方還望大家指正,多多交流,謝謝! 轉載請注明出處!