面試中碰到面試官問:」Spring 註解是若是工做的?「,當前我一驚,完了這不觸及到個人知識誤區了嗎?,還好我機智,靈機一動回了句:Spring 註解的工做流程倒尚未看到,可是我知道@Autowired
註解的工做流程,後面不用說了一頓巴拉,面試官都連連點頭。java
面試中要活用轉移話題,要避免回答 」不知道「,要引導面試官掉入你擅長的技術,而後纔有機會教他做人。面試
@Autowired 註解的主要功能就是完成自動注入,使用也很是簡單(Spring都安排好了),可是要想知道 @Autowired 註解的內部現實,就須要看一下Spring源碼了。接下來一步步的解剖 @Autowired 的實現原理,首先理一下與 @Autowired 註解相關的類,而後一步步的跟蹤源碼,直到理解 @Autowired 的原理。緩存
AutowiredAnnotationBeanPostProcessor
是實現 @Autowired 功能的主要類,它有一些方法是會用解析 @Autowired 註解並實現自動注入的功能,下面是它的繼承圖:架構
從上圖能夠發現 AutowiredAnnotationBeanPostProcessor 最上層是 BeanPostProcessor
是一個後處理器,固然除了後處理器外中間還有InstantiationAwareBeanPostProcessor
和MergedBeanDefinitionPostProcessor
:app
postProcessBeforeInstantiation方法ide
在Bean實例化以前調用,能夠返回一個Bean實例,默認返回null
。post
@Nullabledefault Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { return null;}
postProcessAfterInstantiation方法學習
在Bean建立完成後,設置屬性以前調用。ui
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { return true;}
postProcessProperties方法this
@Nullable default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { return null;}
Bean建立完後,設置屬性以前調用
先記住 InstantiationAwareBeanPostProcessor 接口,後面會跟蹤調用它的地方,就很容易理解了。
MergedBeanDefinitionPostProcessor
也是一個繼承 BeanPostProcessor
接口的後處理器,它的主要做用就是能夠處理操做BeanDefinition
對象,因爲Bean的實例化是經過 BeanDefinition 的, 經過操做BeanDefinition ,這樣能夠使Bean的實例化時發生一些變化。
MergedBeanDefinitionPostProcessor 只有兩個方法
postProcessMergedBeanDefinition方法
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
Bean的BeanDefinition 被合併後調用此方法。
resetBeanDefinition
default void resetBeanDefinition(String beanName) {}
當一個BeanDefinition被重置後調用 。
AutowireCapableBeanFactory
繼承自BeanFactory
,除了提供基礎的Bean操做外,從接口的名字就能夠推斷出的它還有自動注入
的能力。AutowireCapableBeanFactory 提供四種注入模型:
AutowireCapableBeanFactory 接口有很多方法,但大部分都是跟自動注入的相關。@Autowired 的主要功能就是在Bean實例化後,爲其設置屬性,因此在 AutowireCapableBeanFactory 接口有一個 createBean
方法,用於建立Bean並設置Bean的屬性:
<T> T createBean(Class<T> beanClass) throws BeansException;
createBean
方法,它的調用時機是建立Bean的時候,稍後會說到它的調用時機。
AbstractAutowireCapableBeanFactory 繼承 AbstractBeanFactory
並實現了AutowireCapableBeanFactory
接口,因此它也實現了AutowireCapableBeanFactory
中的createBean
方法。
public <T> T createBean(Class<T> beanClass) throws BeansException { // Use prototype bean definition, to avoid registering bean as dependent bean. RootBeanDefinition bd = new RootBeanDefinition(beanClass); bd.setScope(SCOPE_PROTOTYPE); bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader()); return (T) createBean(beanClass.getName(), bd, null);}
經過了解Bean建立的生命週期,才能夠將上面與 @Autowired 相關的類串起來,首先這裏不會過多的介紹Bean的建立細節,只關注自動注入相關的代碼。
Spring中默認的Bean都是懶加載的,因此一個Bean的建立會從調用getBean
方法開始,若是不考慮緩存、上層容器的狀況,Bean的建立會通過如下方法:
以上流程中的getBean
和doGetBean
很少做說明了, 重點關注createBean
前面提到AbstractAutowireCapableBeanFactory.createBean
方法,因此說你在調用getBean
方法獲取Bean的實例時,若是這個Bean實例尚未被建立,那麼createBean
就會被調用。
經過簡單的說明Bean建立的生命週期,就能找到 @Autowired 註解實現的入口,接下來再繼續跟蹤createBean
方法。
收集註入元信息的步驟的,其實就是調用AutowiredAnnotationBeanPostProcessor
類方法來實現的。
如下是createBean
方法,在Bean建立以前調用postProcessBeforeInstantiation
的地方。爲是閱讀方便省略了一些代碼,大體的流程就是:
resolveBeforeInstantiation
方法,執行 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
方法postProcessBeforeInstantiation
返回Bean實例那麼直接返回這個實例,若是返回nul 繼續調用doCreateBean
@Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { ... 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) { ... } ... Object beanInstance = doCreateBean(beanName, mbdToUse, args); ... ... } @Nullable protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null); } return bean; }
這裏 AutowiredAnnotationBeanPostProcessor 的 postProcessBeforeInstantiation 的方法會被調用,因爲AutowiredAnnotationBeanPostProcessor 並無重寫這個方法,因此什麼都不作。
上面說過 postProcessBeforeInstantiation 方法返回 null 的話會繼續執行doCreateBean
方法:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // 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; } } ... populateBean(beanName, mbd, instanceWrapper); ...
在 doCreateBean 方法中,會調用調用applyMergedBeanDefinitionPostProcessors
方法:
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); } }
MergedBeanDefinitionPostProcessor
接口上面提到到的,AutowiredAnnotationBeanPostProcessor 實現了這個接口因此直接進入到 AutowiredAnnotationBeanPostProcessor 中的 postProcessMergedBeanDefinition
方法:
@Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null); metadata.checkConfigMembers(beanDefinition); }
接着繼續進入到findAutowiringMetadata
,findAutowiringMetadata 會調用buildAutowiringMetadata
方法建立注入元數據,而後將元數據緩存到injectionMetadataCache
屬性中:
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable 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)) { ... metadata = buildAutowiringMetadata(clazz); this.injectionMetadataCache.put(cacheKey, metadata); } } } return metadata; }
仔細查看buildAutowiringMetadata
方法的實現,它會反射類的方法和屬性,同時還會向上查找父類,而後生成InjectionMetadata
。
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) { if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) { return InjectionMetadata.EMPTY; } List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); Class<?> targetClass = clazz; do { final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>(); ReflectionUtils.doWithLocalFields(targetClass, field -> { MergedAnnotation<?> ann = findAutowiredAnnotation(field); if (ann != null) { if (Modifier.isStatic(field.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static fields: " + field); } return; } boolean required = determineRequiredStatus(ann); currElements.add(new AutowiredFieldElement(field, required)); } }); ReflectionUtils.doWithLocalMethods(targetClass, method -> { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod); if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static methods: " + method); } return; } if (method.getParameterCount() == 0) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation should only be used on methods with parameters: " + method); } } boolean required = determineRequiredStatus(ann); PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); currElements.add(new AutowiredMethodElement(method, required, pd)); } }); elements.addAll(0, currElements); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); return InjectionMetadata.forElements(elements, clazz); }
收集註入元數據過程,首先調用AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition
方法,而後調用findAutowiringMetadata
方法查找元數據,若是找到相應類的注入元數據 ,就會調用buildAutowiringMetadata
方法建立InjectionMetadata
,最後將新建立的注入元數據保存在injectionMetadataCache
緩存起來。
收信完注入元數據後,Bean的屬性仍是沒有注入的,還須要將執行屬性注入。仍是在doCreateBean
方法中,收集完注入元數據後,緊接着會調用populateBean
:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { 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); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } }
能夠看到在populateBean
中會調用InstantiationAwareBeanPostProcessor.postProcessProperties
方法,因爲已經知道 AutowiredAnnotationBeanPostProcessor 是實現 InstantiationAwareBeanPostProcessor 的,因此能夠直接查看實現方法:
@Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex); } return pvs; }
postProcessProperties
就很簡單的,查找 InjectMetadata,而後調用 InjectMetadata.inject
方法。到這裏其實就已經知道@Autowire
的實現機制了,接下來就是根據InjectionMetadata
中的信息實現屬性注入了。
若是須要深刻研究的話,有興趣的還能夠繼續往下看。
本文大體講解了 @Autowire 相關的類與實現的機制,@Autowire 註解的實現主要是理解AutowiredAnnotationBeanPostProcessor
類,還有收集註入元數據、設置注入屬性的調用時機。
經過查看AutowiredAnnotationBeanPostProcessor
類源碼,相信你也能夠自定義注入功能。
本人知識水平有限,若有錯誤,謝謝你們指正。
歡迎關注個人公衆號:架構文摘,得到獨家整理120G的免費學習資源助力你的架構師學習之路!公衆號後臺回覆
arch028
獲取資料: