Spring原始碼解析(四) -- getBean(String name, Class<T> requiredType)
前言
早在分析beanFactoryPostProcessor的時候,就出現了BeanFactory.getBean方法,因為每一個beanFactoryPostProcessor也是spring管理的bean,也是要經過spring例項化和初始化才能夠使用的,只是當時該方法還不是要分析的重點。
1 查詢快取
final String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons.Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); }else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); }
這部分是先查詢該bean是否在之前有過快取,有就直接使用了,還有一種情況是該bean是一個beanFactory那麼就呼叫beanFactory的getObject方法
2 從父容器中初始化bean
// Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } }
程式碼的作用比較清晰
3 開始例項化
try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); getBean(dep); } }
注意這裡的mergedBeanDefinition,根據文件beanDefinition也是有繼承關係的。注意不是真的類的繼承關係,我寫的程式碼測試B繼承A,但是還是兩個BeanDefinition。
mergedBeanDefinitions 是在 AbstractBeanFactory裡的
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<String, RootBeanDefinition>(256);
而儲存所有的beanDefinition是在DefaultListableBeanFactory的
/** Map of bean definition objects, keyed by bean name */ private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
總之一句話,一個beanDefinition會經過轉換變成mergedBeanDefinition,儘管大多數的beanDefinition還是保持著原樣。而接下來的例項化一個bean就是使用mergedBeanDefinition。
這裡做的第二件事是例項化該bean所依賴的bean。注意這裡的dependon並不是指@Autowired這種依賴注入,而是大概這種方式
<bean id="cat" class="com.lyc.cn.day08.Cat" p:name="美美" depends-on="dog"/>
同樣的上面說的mergedBeanDefinition也不是指兩個類之間的繼承關係,而是這種通過配置檔案配出來的兩個bean的關係
<bean id="parentBean" abstract="true"> <property name="name" value="我是父親"/> </bean> <bean id="sunBean" class="com.lyc.cn.day08.SunBean" parent="parentBean"> <property name="age" value="18"/> </bean>
接下來就是正式的例項化過程了
4AbstractAutowireCapableBeanFactory.createBean
第一部分
if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and // clone the bean definition in case of a dynamically resolved Class // which cannot be stored in the shared merged bean definition. Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); }
特別注意,// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. spring的動態代理就是在這裡被執行的。
第二部分
AbstractAutowireCapableBeanFactory.doCreateBean
// Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); }
真正進行例項化的程式碼就在createBeanInstance 裡,
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); 對於絕大部分bean來說都是通過反射,利用class拿到構造方法,再用構造方法例項化物件,這裡不再展開。
回到doCreateBean繼續分析
快取需要依賴注入的元資訊
// Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } }
applyMergedBeanDefinitionPostProcessors 的是就是這樣的,那麼MergedBeanDefinitionPostProcessor的實現類有哪些呢?還真有一個比較有名的AutowiredAnnotationBeanPostProcessor。AutowiredAnnotationBeanPostProcessor是能夠處理@Autowired和@Value這樣的註解的
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof MergedBeanDefinitionPostProcessor) { MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp; bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName); } } }
我們來看看AutowiredAnnotationBeanPostProcessor的postProcessMergedBeanDefinition幹了啥。
@Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { if (beanType != null) { InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null); metadata.checkConfigMembers(beanDefinition); } }
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs) { // Fall back to class name as cache key, for backwards compatibility with custom callers. String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); // Quick check on the concurrent map first, with minimal locking. InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { synchronized (this.injectionMetadataCache) { metadata = this.injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { if (metadata != null) { metadata.clear(pvs); } try { metadata = buildAutowiringMetadata(clazz); this.injectionMetadataCache.put(cacheKey, metadata); }
findAutowiringMetadata方法是很長的,這裡只擷取一段程式碼看看意思。
buildAutowiringMetadata構造出來一個要注入的元資料物件,同時快取在 injectionMetadataCache裡面,快取的key就是
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
InjectionMetadata 是什麼呢,就是一個物件裡哪個屬性是需要注入的(其他的由spring管理的物件,而不是基本型別)。
這些快取資訊AutowiredAnnotationBeanPostProcessor在後續程式碼執行中會用到的。
再次回到doCreateBean繼續分析
解決迴圈依賴的
// Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); }
解決迴圈依賴的
屬性注入及初始化
最重要的兩個方法,populateBean和initializeBean
populateBean是解決一個bean屬性初始值的
initializeBean是呼叫初始化方法的,比如@PostConstruct,配置檔案裡的init-method,和實現了InitializingBean介面的介面方法
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
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; } //上面的程式碼現在幾乎不會走到,都是為了相容老程式碼的,而且像@Autowired等註解也不走到裡面 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) {//迴圈遍歷每一個beanPostProcessor呼叫他們的postProcessPropertyValues if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } }
不妨我們還是以AutowiredAnnotationBeanPostProcessor的 方法來舉例
public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException { InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); } catch (BeanCreationException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex); } return pvs; }
之前在快取需要依賴注入的元資訊 這個小節交代過了, 例項化後會處理一個bean中的標籤@Autowired並快取起來。
現在就可以直接用了
拿到InjectionMetadata metadata 後就呼叫inject。
對於autowired來說他對應的 方法是這樣的
@Override protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable { Field field = (Field) this.member; Object value; if (this.cached) { value = resolvedCachedArgument(beanName, this.cachedFieldValue); } else { DependencyDescriptor desc = new DependencyDescriptor(field, this.required); desc.setContainingClass(bean.getClass()); Set<String> autowiredBeanNames = new LinkedHashSet<String>(1); TypeConverter typeConverter = beanFactory.getTypeConverter(); try { value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);//把依賴的值解析出來 } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); } synchronized (this) { if (!this.cached) { if (value != null || this.required) { this.cachedFieldValue = desc; registerDependentBeans(beanName, autowiredBeanNames); if (autowiredBeanNames.size() == 1) { String autowiredBeanName = autowiredBeanNames.iterator().next(); if (beanFactory.containsBean(autowiredBeanName)) { if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { this.cachedFieldValue = new ShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType()); } } } } else { this.cachedFieldValue = null; } this.cached = true; } } } if (value != null) { ReflectionUtils.makeAccessible(field); field.set(bean, value);//反射方法直接塞進去 } }
initializeBean
到了執行初始化方法的時候了,這裡說的初始化有三種,@PostConstruct,bean實現了initializingBean介面,和配置了init-method方法,這三種情況的執行。
先看程式碼
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override 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);//就在這裡執行的@PostConstruct } try { invokeInitMethods(beanName, wrappedBean, mbd);//先initializingBean介面,而後才是init-method方法
} 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原bean } return wrappedBean; }