http://www.javashuo.com/article/p-uvudtich-bm.htmlhtml
在前面的幾篇文章中,咱們屢次提到這麼一個轉化過程:java
Bean配置 --> BeanDefinition --> Bean對象web
Bean的配置能夠是xml配置,也能夠是java配置。BeanDefinition配置在內存中數據對象,也是Bean的元數據。在springboot啓動過程中,refresh上下文這個步驟將會解析xml配置以及java配置,從而把Bean的配置解析成爲BeanDefinition。咱們也能夠將這個過程簡稱爲Bean的元數據生成。spring
這裏咱們須要注意!refresh只是把BeanDefinition註冊到BeanFactory中,而不是把Bean註冊到BeanFactory中。(這裏咱們不討論non-lazy-init=true的狀況)緩存
而是在咱們調用上下文的getBean的時候纔會去根據BeanDefinition生成springboot
@Override public Object getBean(String name) throws BeansException { // return getBeanFactory().getBean(name); }
上下文的getBean方法把功能實現委託給了BeanFactory,跟進AbstractBeanFactory的getBean方法app
@Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); }
跟進doGetBean方法ide
protected <T> T doGetBean( final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; // 若是拿到已經註冊的單例Bean,直接返回結果 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { // bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // // 建立單例 if (mbd.isSingleton()) { // 回調建立 sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { Object prototypeInstance = null; try { beforePrototypeCreation(beanName); // 每次建立 prototypeInstance = createBean(beanName, mbd, args); } finally { // } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { // } } catch (BeansException ex) { // } } // return (T) bean; }
該方法的邏輯是先去單例的緩存中找,若是找獲得直接返回。若是找不到,那麼判斷是單例仍是原型,若是是單例建立並緩存,若是是原型那麼每次都建立新的。post
跟進建立單例的時候的getSingleton方法ui
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { // 內置鎖控制 synchronized (this.singletonObjects) { // 雙重校驗 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { // boolean newSingleton = false; // try { // 回調建立Bean singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { // } catch (BeanCreationException ex) { // } finally { // } if (newSingleton) { // 添加單例到緩存中 addSingleton(beanName, singletonObject); } } return singletonObject; } }
這裏採用雙重校驗機制控制了單例,若是二次校驗的時候發現緩存中沒有Bean,那麼就會回調建立的方法去建立一個Bean,而後再註冊到本地堆緩存當中。
咱們先回到調用getSingleton的方法位置,看一下回調方法實什麼
if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }
建立實現委託給了createBean方法,該方法的實現屬於AbstractAutowireCapableBeanFactory,跟進該類的CreateBean方法
@Override protected Object createBean( String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // RootBeanDefinition mbdToUse = mbd; // try { // 建立Bean實例 Object beanInstance = doCreateBean(beanName, mbdToUse, args); // return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // } catch (Throwable ex) { // } }
繼續跟進doCreateBean
protected Object doCreateBean( final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // 建立Bean實例對象 BeanWrapper instanceWrapper = null; // if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } // try { // 自動注入 populateBean(beanName, mbd, instanceWrapper); // } catch (Throwable ex) { // } // return exposedObject; }
該方法主要包含兩個步驟,建立Bean的實例對象和自動注入
跟進createBeanInstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // 省略 // 默認使用無參數構造方法獲取實例 return instantiateBean(beanName, mbd); }
跟進instantiateBean方法
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy(); protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { try { Object beanInstance; final BeanFactory parent = this; if (System.getSecurityManager() != null) { beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () -> // 實例化 getInstantiationStrategy().instantiate(mbd, beanName, parent), getAccessControlContext()); } else { // 實例化 beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); } BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw; } catch (Throwable ex) { // } } // 獲取實例化策略 protected InstantiationStrategy getInstantiationStrategy() { return this.instantiationStrategy; }
默認的實例化策略是CglibSubclassingInstantiationStrategy,它又繼承自SimpleInstantiationStrategy,跟進SimpleInstantiationStrategy類的instantiate方法
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { // 若是不存在須要被重寫的方法,那麼就不須要使用cglib重寫並覆蓋該類 if (!bd.hasMethodOverrides()) { Constructor<?> constructorToUse; synchronized (bd.constructorArgumentLock) { // } // 經過構造方法實例化 return BeanUtils.instantiateClass(constructorToUse); } else { // 須要經過cglib生成 return instantiateWithMethodInjection(bd, beanName, owner); } }
到這裏,BeanDefinition就被初步建立成爲了一個Bean實例對象。
前面咱們說到,doCreateBean有兩個步驟
1)建立Bean實例對象
2)自動注入
回顧一下doCreateBean的代碼
protected Object doCreateBean( final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // 建立Bean實例對象 BeanWrapper instanceWrapper = null; // if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } // try { // 自動注入 populateBean(beanName, mbd, instanceWrapper); // } catch (Throwable ex) { // } // return exposedObject; }
接下來,咱們跟進populateBean方法看看當前這個建立好的Bean實例實怎麼注入其它Bean的
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // // 獲取待注入的property,配置文件中配置的<property>將在這裏被處理 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // 按照名字或者類型獲取屬性,這裏會進行遞歸 if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // 按照名字獲取屬性 if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // 按照類型獲取屬性 if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } 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) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } // 後置處理器處理@Autowired @Resource等註解 pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } // 注入<property>屬性 if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }
咱們看到populateBean主要作兩件事,獲取屬性值,而後把屬性值給注入到Bean裏面去。咱們重點關注後置處理器處理@Autowired @Resource註解的邏輯。
跟進AutowiredAnnotationBeanPostProcessor類的postProcessPropertyValues方法
public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) { return postProcessProperties(pvs, bean, beanName); }
跟進postProcessProperties方法
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { // 獲取當前Bean的元數據,將包含@Autowired等註解的標註的待注入元素 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等註解標註的待注入的元素,而後注入相應的到元素。
跟進findAutowiringMetadata方法
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { . String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); 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); } // 構造元數據 metadata = buildAutowiringMetadata(clazz); this.injectionMetadataCache.put(cacheKey, metadata); } } } return metadata; }
繼續跟進buildAutowiringMetadata
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) { List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); Class<?> targetClass = clazz; do { final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>(); ReflectionUtils.doWithLocalFields(targetClass, field -> { // 找到註解@Autowired AnnotationAttributes ann = findAutowiredAnnotation(field); if (ann != null) { // boolean required = determineRequiredStatus(ann); currElements.add(new AutowiredFieldElement(field, required)); } }); // elements.addAll(0, currElements); // 往父類遞歸 targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); return new InjectionMetadata(clazz, elements); }
這裏找到註解@Autowired的Field之後包裝成Element,而後向父類遞歸,最後包裝成元數據
咱們回到postProcessProperties方法之後,再跟進inject注入方法看看
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs) throws Throwable { if (this.isField) { Field field = (Field) this.member; ReflectionUtils.makeAccessible(field); // 反射設置值,這裏的取值會對依賴進行遞歸處理 field.set(target, getResourceToInject(target, requestingBeanName)); } else { // 省略 } }
這裏主要是對Bean的Field的一個反射來設置值,值的獲取將會進行遞歸處理
觸發後置處理器的邏輯跟AutowiredAnnotationBeanPostProcessor是同樣的,咱們直接來看看CommonAnnotationBeanPostProcessor的buildAutowiringMetadata方法
private InjectionMetadata buildResourceMetadata(final Class<?> clazz) { List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); Class<?> targetClass = clazz; do { final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>(); ReflectionUtils.doWithLocalFields(targetClass, field -> { if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) { // } else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) { // } // 若是註解了@Resource else if (field.isAnnotationPresent(Resource.class)) { // if (!this.ignoredResourceTypes.contains(field.getType().getName())) { // 添加element currElements.add(new ResourceElement(field, field, null)); } } }); // elements.addAll(0, currElements); // 向父類遞歸 targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); return new InjectionMetadata(clazz, elements); }
元數據返回之後的流程和@Autowired也是同樣的。
本文粗略地過了一下ioc依賴注入的過程,從BeanDefinition --> Bean的過程。咱們一開始建立了Bean的實例,而後再經過遞歸解析依賴注入處理把Bean之間的關係結合處理。在最後還提了一下@Autowired和@Resource的後置處理器。
依賴注入的過程相對來講仍是很複雜的,包含了很是多的細節處理。可是咱們能夠簡單地去歸納一下它,整個依賴注入的過程就是建立Bean,並創建Bean之間的關係。