1. 程式人生 > >死磕Spring之IoC篇 - @Autowired 等註解的實現原理

死磕Spring之IoC篇 - @Autowired 等註解的實現原理

> 該系列文章是本人在學習 Spring 的過程中總結下來的,裡面涉及到相關原始碼,可能對讀者不太友好,請結合我的原始碼註釋 [Spring 原始碼分析 GitHub 地址](https://github.com/liu844869663/spring-framework) 進行閱讀 > > Spring 版本:5.1.14.RELEASE > > 開始閱讀這一系列文章之前,建議先檢視[**《深入瞭解 Spring IoC(面試題)》**](https://www.cnblogs.com/lifullmoon/p/14422101.html)這一篇文章 > > 該系列其他文章請檢視:[**《死磕 Spring 之 IoC 篇 - 文章導讀》**](https://www.cnblogs.com/lifullmoon/p/14436372.html) ## @Autowired 等註解的實現原理 在上一篇[**《Bean 的屬性填充階段》**](https://www.cnblogs.com/lifullmoon/p/14452969.html)文章中講到,在建立一個 Bean 的例項物件後,會對這個 Bean 進行屬性填充。在屬性填充的過程中,獲取到已定義的屬性值,然後會通過 InstantiationAwareBeanPostProcessor 對該屬性值進行處理,最後通過反射機制將屬性值設定到這個 Bean 中。在 Spring 內部有以下兩個 InstantiationAwareBeanPostProcessor 處理器: - **AutowiredAnnotationBeanPostProcessor**,解析 @Autowired 和 @Value 註解標註的屬性,獲取對應屬性值 - **CommonAnnotationBeanPostProcessor**,會解析 @Resource 註解標註的屬性,獲取對應的屬性值 本文將會分析這兩個處理器的實現,以及涉及到的相關物件 ### 這兩個處理器在哪被註冊? 在前面的[**《解析自定義標籤(XML 檔案)》**](https://www.cnblogs.com/lifullmoon/p/14449414.html) 和 [**《BeanDefinition 的解析過程(面向註解)》**](https://www.cnblogs.com/lifullmoon/p/14451788.html)文章中可以知道,在 XML 檔案中的 `
` 標籤的處理過程中,會底層藉助於 `ClassPathBeanDefinitionScanner` 掃描器,去掃描指定路徑下符合條件(@Component 註解)的 BeanDefinition 們,關於 @ComponentScan 註解的解析也是藉助於這個掃描器實現的。掃描過程如下: ```java // ClassPathBeanDefinitionScanner.java public int scan(String... basePackages) { // <1> 獲取掃描前的 BeanDefinition 數量 int beanCountAtScanStart = this.registry.getBeanDefinitionCount(); // <2> 進行掃描,將過濾出來的所有的 .class 檔案生成對應的 BeanDefinition 並註冊 doScan(basePackages); // Register annotation config processors, if necessary. // <3> 如果 `includeAnnotationConfig` 為 `true`(預設),則註冊幾個關於註解的 PostProcessor 處理器(關鍵) // 在其他地方也會註冊,內部會進行判斷,已註冊的處理器不會再註冊 if (this.includeAnnotationConfig) { AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); } // <4> 返回本次掃描註冊的 BeanDefinition 數量 return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart); } ``` 在第 `<3>` 步會呼叫 AnnotationConfigUtils 的 `registerAnnotationConfigProcessors(BeanDefinitionRegistry)` 方法,如下: ```java // AnnotationConfigUtils.java public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) { registerAnnotationConfigProcessors(registry, null); } /** * Register all relevant annotation post processors in the given registry. * @param registry the registry to operate on * @param source the configuration source element (already extracted) * that this registration was triggered from. May be {@code null}. * @return a Set of BeanDefinitionHolders, containing all bean definitions * that have actually been registered by this call */ public static Set registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) { DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); if (beanFactory != null) { if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); } } Set beanDefs = new LinkedHashSet<>(8); // 處理 Spring 應用上下文中的配置類 if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } // 處理 @Autowired 以及 @Value 註解 if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } // (條件啟用)處理 JSR-250 註解 @Resource,如 @PostConstruct、@PreDestroy 等 // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor. if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); } // Processor 物件(條件啟用)處理 JPA 註解場景 // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor. if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(); try { def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader())); } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex); } def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)); } // 處理標註 @EventListener 的 Spring 事件監聽方法 if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME)); } // 用於 @EventListener 標註的事件監聽方法構建成 ApplicationListener 物件 if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME)); } return beanDefs; } ``` 在這個方法中可以看到會註冊 **AutowiredAnnotationBeanPostProcessor** 和 **CommonAnnotationBeanPostProcessor** 兩個處理器,然後在 Spring 應用上下文重新整理階段會將其初始化並新增至 AbstractBeanFactory 的 `beanPostProcessors` 集合中,那麼接下來我們先來分析這兩個處理器 ### 回顧 Bean 的建立過程 第一步:回到[**《Bean 的建立過程》**](https://www.cnblogs.com/lifullmoon/p/14452842.html)文章中的“對 RootBeanDefinition 加工處理”小節,會呼叫這個方法: ```java // AbstractAutowireCapableBeanFactory.java 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 的 **postProcessMergedBeanDefinition** 方法對 RootBeanDefinition 進行加工處理,例如: - AutowiredAnnotationBeanPostProcessor,會先解析出 `@Autowired` 和 `@Value` 註解標註的屬性的注入元資訊,後續進行依賴注入 - CommonAnnotationBeanPostProcessor,會先解析出 `@Resource` 註解標註的屬性的注入元資訊,後續進行依賴注入,它也會找到 `@PostConstruct` 和 `@PreDestroy` 註解標註的方法,並構建一個 LifecycleMetadata 物件,用於後續生命週期中的初始化和銷燬 第二步:回到[**《Bean 的建立過程》**](https://www.cnblogs.com/lifullmoon/p/14452842.html)文章中的“屬性填充”小節,該過程會進行下面的處理: ```java // <5> 通過 InstantiationAwareBeanPostProcessor 處理器(如果有)對 `pvs` 進行處理 if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } // <5.1> 遍歷所有的 BeanPostProcessor for (BeanPostProcessor bp : getBeanPostProcessors()) { // 如果為 InstantiationAwareBeanPostProcessor 型別 if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // <5.2> 呼叫處理器的 `postProcessProperties(...)` 方法,對 `pvs` 進行後置處理 PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); // <5.3> 如果上一步的處理結果為空,可能是新版本導致的(Spring 5.1 之前沒有上面這個方法),則需要相容老版本 if (pvsToUse == null) { // <5.3.1> 找到這個 Bean 的所有 `java.beans.PropertyDescriptor` 屬性描述器(包含這個屬性的所有資訊) if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } // <5.3.2> 呼叫處理器的 `postProcessPropertyValues(...)` 方法,對 `pvs` 進行後置處理 pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); // <5.3.3> 如果處理後的 PropertyValues 物件為空,直接 `return`,則不會呼叫後面的 InstantiationAwareBeanPostProcessor 處理器,也不會進行接下來的屬性填充 if (pvsToUse == null) { return; } } // <5.4> 將處理後的 `pvsToUse` 複製給 `pvs` pvs = pvsToUse; } } } ``` 這裡不會呼叫所有 InstantiationAwareBeanPostProcessor 的 **postProcessProperties** 方法對 `pvs`(MutablePropertyValues)屬性值物件進行處理,例如: - AutowiredAnnotationBeanPostProcessor,會根據前面解析出來的 `@Autowired` 和 `@Value` 註解標註的屬性的注入元資訊,進行**依賴注入** - CommonAnnotationBeanPostProcessor,會根據前面解析出來的 `@Resource` 註解標註的屬性的注入元資訊,進行**依賴注入** 可以看到`@Autowired`、`@Value` 和 `@Resource` 註解的實現就是基於這兩個處理器實現的,接下來我們來看看這兩個處理器的具體實現 ### AutowiredAnnotationBeanPostProcessor `org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor`,主要處理 `@Autowired` 和 `@Value` 註解進行依賴注入 #### 體系結構
可以看到 AutowiredAnnotationBeanPostProcessor 實現了 MergedBeanDefinitionPostProcessor 和 InstantiationAwareBeanPostProcessor 兩個介面 #### 構造方法 ```java public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware { /** * 儲存需要處理的註解 */ private final Set> autowiredAnnotationTypes = new LinkedHashSet<>(4); private String requiredParameterName = "required"; private boolean requiredParameterValue = true; private int order = Ordered.LOWEST_PRECEDENCE - 2; @Nullable private ConfigurableListableBeanFactory beanFactory; private final Set lookupMethodsChecked = Collections.newSetFromMap(new ConcurrentHashMap<>(256)); private final Map, Constructor[]> candidateConstructorsCache = new ConcurrentHashMap<>(256); /** * 快取需要注入的欄位元資訊 */ private final Map injectionMetadataCache = new ConcurrentHashMap<>(256); /** * Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's * standard {@link Autowired @Autowired} annotation. *

Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation, * if available. */ @SuppressWarnings("unchecked") public AutowiredAnnotationBeanPostProcessor() { this.autowiredAnnotationTypes.add(Autowired.class); this.autowiredAnnotationTypes.add(Value.class); try { this.autowiredAnnotationTypes.add((Class) ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader())); logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring"); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip. } } } ``` 可以看到會新增 `@Autowired` 和 `@Value` 兩個註解,如果存在 JSR-330 的 `javax.inject.Inject` 註解,也是支援的 #### postProcessMergedBeanDefinition 方法 `postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName)` 方法,找到 `@Autowired` 和 `@Value` 註解標註的欄位(或方法)的元資訊,如下: ```java @Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { // 找到這個 Bean 所有需要注入的屬性(@Autowired 或者 @Value 註解) InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null); metadata.checkConfigMembers(beanDefinition); } ``` 直接呼叫 `findAutowiringMetadata(...)` 方法獲取這個 Bean 的**注入元資訊物件** ##### 1. findAutowiringMetadata 方法 ```java private InjectionMetadata findAutowiringMetadata(String beanName, Class clazz, @Nullable PropertyValues pvs) { // Fall back to class name as cache key, for backwards compatibility with custom callers. // 生成一個快取 Key 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); } // 構建一個需要注入的元資訊物件 metadata = buildAutowiringMetadata(clazz); this.injectionMetadataCache.put(cacheKey, metadata); } } } return metadata; } ``` 首先嚐試從快取中獲取這個 Bean 對應的**注入元資訊物件**,沒有找到的話則呼叫 `buildAutowiringMetadata(final Class clazz)` 構建一個,然後再放入快取中 ##### 2. buildAutowiringMetadata 方法 ```java private InjectionMetadata buildAutowiringMetadata(final Class clazz) { List elements = new ArrayList<>(); Class targetClass = clazz; do { // <1> 建立 `currElements` 集合,用於儲存 @Autowired、@Value 註解標註的欄位 final List currElements = new ArrayList<>(); // <2> 遍歷這個 Class 物件的所有欄位 ReflectionUtils.doWithLocalFields(targetClass, field -> { // <2.1> 找到該欄位的 @Autowired 或者 @Value 註解,返回 `ann` 物件,沒有的話返回空物件,則直接跳過不進行下面的操作 AnnotationAttributes ann = findAutowiredAnnotation(field); if (ann != null) { // <2.2> 進行過濾,static 修飾的欄位不進行注入 if (Modifier.isStatic(field.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static fields: " + field); } return; } // <2.3> 獲取註解中的 `required` 配置 boolean required = determineRequiredStatus(ann); // <2.4> 根據該欄位和 `required` 構建一個 AutowiredFieldElement 物件,新增至 `currElements` currElements.add(new AutowiredFieldElement(field, required)); } }); // <3> 遍歷這個 Class 物件的所有方法 ReflectionUtils.doWithLocalMethods(targetClass, method -> { // <3.1> 嘗試找到這個方法的橋接方法,沒有的話就是本身這個方法 Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); // <3.2> 如果是橋接方法則直接跳過 if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } // <3.3> 找到該方法的 @Autowired 或者 @Value 註解,返回 `ann` 物件,沒有的話返回空物件,則直接跳過不進行下面的操作 AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod); if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { // <3.4> 進行過濾,static 修飾的方法不進行注入 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); } } // <3.5> 獲取註解中的 `required` 配置 boolean required = determineRequiredStatus(ann); PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); // <3.6> 構建一個 AutowiredMethodElement 物件,新增至 `currElements` currElements.add(new AutowiredMethodElement(method, required, pd)); } }); elements.addAll(0, currElements); // <4> 找到父類,迴圈遍歷 targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); // <5> 根據從這個 Bean 解析出來的所有 InjectedElement 物件生成一個 InjectionMetadata 注入元資訊物件,並返回 return new InjectionMetadata(clazz, elements); } ``` 過程如下: 1. 建立 `currElements` 集合,用於儲存 `@Autowired`、`@Value` 註解標註的欄位 2. 遍歷這個 Class 物件的所有欄位 1. 找到該欄位的 `@Autowired` 或者 `@Value` 註解,返回 `ann` 物件,沒有的話返回空物件,則直接跳過不進行下面的操作 2. 進行過濾,static 修飾的欄位不進行注入 3. 獲取註解中的 `required` 配置 4. 根據該欄位和 `required` 構建一個 AutowiredFieldElement 物件,新增至 `currElements` 3. 遍歷這個 Class 物件的所有方法 1. 嘗試找到這個方法的橋接方法,沒有的話就是本身這個方法 2. 如果是橋接方法則直接跳過 3. 找到該方法的 `@Autowired` 或者 `@Value` 註解,返回 `ann` 物件,沒有的話返回空物件,則直接跳過不進行下面的操作 4. 進行過濾,static 修飾的方法不進行注入 5. 獲取註解中的 `required` 配置 6. 構建一個 AutowiredMethodElement 物件,新增至 `currElements` 4. 找到父類,迴圈遍歷 5. 根據從這個 Bean 解析出來的所有 InjectedElement 物件生成一個 InjectionMetadata 注入元資訊物件,並返回 整個過程很簡單,就是解析出所有 `@Autowired` 或者 `@Value` 註解標註的方法或者欄位,然後構建一個 InjectionMetadata 注入元資訊物件 #### postProcessProperties 方法 `postProcessProperties(PropertyValues pvs, Object bean, String beanName)` 方法,根據 `@Autowired` 和 `@Value` 註解標註的欄位(或方法)的元資訊進行**依賴注入**,如下: ```java @Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { // 找到這個 Bean 的注入元資訊物件 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 的注入元資訊物件,上面已經講過了,然後呼叫其 `inject(...)` 方法,這裡先來看到 `InjectionMetadata` 這個物件 ### InjectionMetadata 注入元資訊物件 `org.springframework.beans.factory.annotation.InjectionMetadata`,某個 Bean 的注入元資訊物件 ```java public class InjectionMetadata { private static final Log logger = LogFactory.getLog(InjectionMetadata.class); private final Class targetClass; /** * 需要注入的欄位(或方法)的元資訊 */ private final Collection injectedElements; @Nullable private volatile Set checkedElements; public InjectionMetadata(Class targetClass, Collection elements) { this.targetClass = targetClass; this.injectedElements = elements; } public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Collection checkedElements = this.checkedElements; Collection elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements); if (!elementsToIterate.isEmpty()) { for (InjectedElement element : elementsToIterate) { if (logger.isTraceEnabled()) { logger.trace("Processing injected element of bean '" + beanName + "': " + element); } element.inject(target, beanName, pvs); } } } } ``` 可以看到注入方法非常簡單,就是遍歷所有的 InjectedElement 物件,呼叫他們的 `inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs)` 方法 ### AutowiredFieldElement AutowiredAnnotationBeanPostProcessor 的私有內部類,注入欄位物件,如下: ```java private class AutowiredFieldElement extends InjectionMetadata.InjectedElement { /** 是否必須 */ private final boolean required; /** 是否快取起來了 */ private volatile boolean cached = false; /** 快取的物件 */ @Nullable private volatile Object cachedFieldValue; public AutowiredFieldElement(Field field, boolean required) { super(field, null); this.required = required; } @Override protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { // <1> 獲取 `field` 欄位 Field field = (Field) this.member; Object value; // <2> 如果進行快取了,則嘗試從快取中獲取 if (this.cached) { value = resolvedCachedArgument(beanName, this.cachedFieldValue); } // <3> 否則,開始進行解析 else { // <3.1> 建立一個依賴注入描述器 `desc` DependencyDescriptor desc = new DependencyDescriptor(field, this.required); desc.setContainingClass(bean.getClass()); Set autowiredBeanNames = new LinkedHashSet<>(1); Assert.state(beanFactory != null, "No BeanFactory available"); TypeConverter typeConverter = beanFactory.getTypeConverter(); try { /** * <3.2> 通過 {@link org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency} 方法 * 找到這個欄位對應的 Bean(們) */ value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); } // <3.3> 和快取相關,如果有必要則將本次找到的注入物件快取起來,避免下次再進行解析 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) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { this.cachedFieldValue = new ShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType()); } } } else { this.cachedFieldValue = null; } this.cached = true; } } } // <4> 如果獲取到該欄位對應的物件,則進行屬性賦值(依賴注入) if (value != null) { ReflectionUtils.makeAccessible(field); field.set(bean, value); } } } ``` 直接看到 `inject(...)` 方法,注入的過程如下: 1. 獲取 `field` 欄位 2. 如果進行快取了,則嘗試從快取中獲取 3. 否則,開始進行解析 1. 建立一個依賴注入描述器 `desc` 2. **【核心】**通過 `DefaultListableBeanFactory#resolveDependency(...)` 方法,找到這個欄位對應的 Bean(們) 3. 和快取相關,如果有必要則將本次找到的注入物件快取起來,避免下次再進行解析 4. 如果獲取到該欄位對應的物件,則進行屬性賦值(**依賴注入**),底層就是通過反射機制為該欄位賦值 可以看到整個的**核心**在於通過 `DefaultListableBeanFactory#resolveDependency(...)` 方法找到欄位對應的 Bean,這裡也許是一個集合物件,所以也可能找到的是多個 Bean,該方法在後面進行分析 ### AutowiredMethodElement AutowiredAnnotationBeanPostProcessor 的私有內部類,注入方法物件,如下: ```java private class AutowiredMethodElement extends InjectionMetadata.InjectedElement { /** 是否必須 */ private final boolean required; /** 是否快取起來了 */ private volatile boolean cached = false; /** 快取的方法引數物件 */ @Nullable private volatile Object[] cachedMethodArguments; public AutowiredMethodElement(Method method, boolean required, @Nullable PropertyDescriptor pd) { super(method, pd); this.required = required; } @Override protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { if (checkPropertySkipping(pvs)) { return; } // <1> 獲取 `method` 方法 Method method = (Method) this.member; // <2> 如果進行快取了,則嘗試從快取中獲取方法引數物件 Object[] arguments; if (this.cached) { // Shortcut for avoiding synchronization... arguments = resolveCachedArguments(beanName); } // <3> 否則,開始進行解析 else { // <3.1> 獲取方法的引數型別集合 `paramTypes`,根據引數位置確定引數 Class[] paramTypes = method.getParameterTypes(); arguments = new Object[paramTypes.length]; // <3.2> 構建一個依賴注入描述器陣列 `descriptors`,用於儲存後續建立的物件 DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length]; Set autowiredBeans = new LinkedHashSet<>(paramTypes.length); Assert.state(beanFactory != null, "No BeanFactory available"); TypeConverter typeConverter = beanFactory.getTypeConverter(); // <3.3> 根據引數順序遍歷該方法的引數 for (int i = 0; i < arguments.length; i++) { // <3.3.1> 為第 `i` 個方法引數建立一個 MethodParameter 物件 MethodParameter methodParam = new MethodParameter(method, i); // <3.3.2> 建立依賴描述器 `currDesc`,並新增至 `descriptors` 陣列 DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required); currDesc.setContainingClass(bean.getClass()); descriptors[i] = currDesc; try { /** * <3.3.3> 通過 {@link org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency} 方法 * 找到這個方法引數對應的 Bean(們) */ Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter); if (arg == null && !this.required) { arguments = null; break; } arguments[i] = arg; } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex); } } // <3.4> 和快取相關,如果有必要則將本次找到的方法引數物件快取起來,避免下次再進行解析 synchronized (this) { if (!this.cached) { if (arguments != null) { Object[] cachedMethodArguments = new Object[paramTypes.length]; System.arraycopy(descriptors, 0, cachedMethodArguments, 0, arguments.length); registerDependentBeans(beanName, autowiredBeans); if (autowiredBeans.size() == paramTypes.length) { Iterator it = autowiredBeans.iterator(); for (int i = 0; i < paramTypes.length; i++) { String autowiredBeanName = it.next(); if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) { cachedMethodArguments[i] = new ShortcutDependencyDescriptor( descriptors[i], autowiredBeanName, paramTypes[i]); } } } this.cachedMethodArguments = cachedMethodArguments; } else { this.cachedMethodArguments = null; } this.cached = true; } } } // <4> 如果找到該方法的引數(們),則進行屬性賦值(依賴注入) if (arguments != null) { try { ReflectionUtils.makeAccessible(method); // 通過反射機制呼叫該方法 method.invoke(bean, arguments); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } } } ``` 直接看到 `inject(...)` 方法,注入的過程如下: 1. 獲取 `method` 方法 2. 如果進行快取了,則嘗試從快取中獲取方法引數物件 3. 否則,開始進行解析 1. 獲取方法的引數型別集合 `paramTypes`,根據引數位置確定引數 2. 構建一個依賴注入描述器陣列 `descriptors`,用於儲存後續建立的物件 3. 根據引數順序遍歷該方法的引數 1. 為第 `i` 個方法引數建立一個 MethodParameter 物件 2. 建立依賴描述器 `currDesc`,並新增至 `descriptors` 陣列 3. **【核心】**通過 `DefaultListableBeanFactory#resolveDependency(...)` 方法,找到這個方法引數對應的 Bean(們) 4. 和快取相關,如果有必要則將本次找到的方法引數物件快取起來,避免下次再進行解析 4. 如果找到該方法的引數(們),則進行屬性賦值(**依賴注入**),底層就是通過反射機制呼叫該方法 可以看到整個的**核心**也是通過 `DefaultListableBeanFactory#resolveDependency(...)` 方法找到方法引數對應的 Bean,該方法在後面進行分析 ### CommonAnnotationBeanPostProcessor `org.springframework.context.annotation.CommonAnnotationBeanPostProcessor`,主要處理 `@Resource` 註解進行依賴注入,以及 `@PostConstruct` 和 `@PreDestroy` 生命週期註解的處理 #### 體系結構

可以看到 CommonAnnotationBeanPostProcessor 實現了 MergedBeanDefinitionPostProcessor 和 InstantiationAwareBeanPostProcessor 兩個介面,還實現了 DestructionAwareBeanPostProcessor 介面,用於生命週期中的初始化和銷燬的處理 #### 構造方法 ```java public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable { @Nullable private static Class webServiceRefClass; @Nullable private static Class ejbRefClass; static { try { @SuppressWarnings("unchecked") Class clazz = (Class) ClassUtils.forName("javax.xml.ws.WebServiceRef", CommonAnnotationBeanPostProcessor.class.getClassLoader()); webServiceRefClass = clazz; } catch (ClassNotFoundException ex) { webServiceRefClass = null; } try { @SuppressWarnings("unchecked") Class clazz = (Class) ClassUtils.forName("javax.ejb.EJB", CommonAnnotationBeanPostProcessor.class.getClassLoader()); ejbRefClass = clazz; } catch (ClassNotFoundException ex) { ejbRefClass = null; } } /** * Create a new CommonAnnotationBeanPostProcessor, * with the init and destroy annotation types set to * {@link javax.annotation.PostConstruct} and {@link javax.annotation.PreDestroy}, * respectively. */ public CommonAnnotationBeanPostProcessor() { setOrder(Ordered.LOWEST_PRECEDENCE - 3); setInitAnnotationType(PostConstruct.class); setDestroyAnnotationType(PreDestroy.class); ignoreResourceType("javax.xml.ws.WebServiceContext"); } } public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, Serializable { protected transient Log logger = LogFactory.getLog(getClass()); /** * 初始化註解,預設為 @PostConstruct */ @Nullable private Class initAnnotationType; /** * 銷燬註解,預設為 @PreDestroy */ @Nullable private Class destroyAnnotationType; private int order = Ordered.LOWEST_PRECEDENCE; @Nullable private final transient Map, LifecycleMetadata> lifecycleMetadataCache = new ConcurrentHashMap<>(256); public void setInitAnnotationType(Class initAnnotationType) { this.initAnnotationType = initAnnotationType; } public void setDestroyAnnotationType(Class destroyAnnotationType) { this.destroyAnnotationType = destroyAnnotationType; } } ``` 可以看到會設定初始化註解為 `@PostConstruct`,銷燬註解為 `@PreDestroy`,這兩個註解都是 JSR-250 註解;另外如果存在 `javax.xml.ws.WebServiceRef` 和 `javax.ejb.EJB` 註解也是會進行設定的 #### postProcessMergedBeanDefinition 方法 `postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName)` 方法,找到 `@PostConstruct` 和 `@PreDestroy` 註解標註的方法,並構建 LifecycleMetadata 物件,找到 `@Resource` 註解標註的欄位(或方法)的元資訊,如下: ```java // CommonAnnotationBeanPostProcessor.java @Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { // 先呼叫父類的方法,找到 @PostConstruct 和 @PreDestroy 註解標註的方法,並構建 LifecycleMetadata 物件 super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName); // 找到 @Resource 註解標註的欄位(或方法),構建一個 InjectionMetadata 物件,用於後續的屬性注入 InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null); metadata.checkConfigMembers(beanDefinition); } ``` 整個的過程原理和 AutowiredAnnotationBeanPostProcessor 差不多,先從快取中獲取,未命中則呼叫對應的方法進行構建,下面先來看看父類中的方法 ##### buildLifecycleMetadata 方法 ```java // InitDestroyAnnotationBeanPostProcessor.java private LifecycleMetadata buildLifecycleMetadata(final Class clazz) { List initMethods = new ArrayList<>(); List destroyMethods = new ArrayList<>(); Class targetClass = clazz; do { final List currInitMethods = new ArrayList<>(); final List currDestroyMethods = new ArrayList<>(); ReflectionUtils.doWithLocalMethods(targetClass, method -> { if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) { LifecycleElement element = new LifecycleElement(method); currInitMethods.add(element); if (logger.isTraceEnabled()) { logger.trace("Found init method on class [" + clazz.getName() + "]: " + method); } } if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) { currDestroyMethods.add(new LifecycleElement(method)); if (logger.isTraceEnabled()) { logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method); } } }); initMethods.addAll(0, currInitMethods); destroyMethods.addAll(currDestroyMethods); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); return new LifecycleMetadata(clazz, initMethods, destroyMethods); } ``` 整個過程比較簡單,找到這個 Bean 中 `@PostConstruct` 和 `@PreDestroy` 註解標註的方法,然後構建一個 LifecycleMetadata 生命週期元資訊物件 ##### buildResourceMetadata 方法 ```java // CommonAnnotationBeanPostProcessor.java private InjectionMetadata buildResourceMetadata(final Class clazz) { List elements = new ArrayList<>(); Class targetClass = clazz; do { final List currElements = new ArrayList<>(); ReflectionUtils.doWithLocalFields(targetClass, field -> { if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) { if (Modifier.isStatic(field.getModifiers())) { throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields"); } currElements.add(new WebServiceRefElement(field, field, null)); } else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) { if (Modifier.isStatic(field.getModifiers())) { throw new IllegalStateException("@EJB annotation is not supported on static fields"); } currElements.add(new EjbRefElement(field, field, null)); } else if (field.isAnnotationPresent(Resource.class)) { if (Modifier.isStatic(field.getModifiers())) { throw new IllegalStateException("@Resource annotation is not supported on static fields"); } if (!this.ignoredResourceTypes.contains(field.getType().getName())) { currElements.add(new ResourceElement(field, field, null)); } } }); ReflectionUtils.doWithLocalMethods(targetClass, method -> { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) { if (Modifier.isStatic(method.getModifiers())) { throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods"); } if (method.getParameterCount() != 1) { throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method); } PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); currElements.add(new WebServiceRefElement(method, bridgedMethod, pd)); } else if (ejbRefClass != null && bridgedMethod.isAnnotationPresent(ejbRefClass)) { if (Modifier.isStatic(method.getModifiers())) { throw new IllegalStateException("@EJB annotation is not supported on static methods"); } if (method.getParameterCount() != 1) { throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method); } PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); currElements.add(new EjbRefElement(method, bridgedMethod, pd)); } else if (bridgedMethod.isAnnotationPresent(Resource.class)) { if (Modifier.isStatic(method.getModifiers())) { throw new IllegalStateException("@Resource annotation is not supported on static methods"); } Class[] paramTypes = method.getParameterTypes(); if (paramTypes.length != 1) { throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method); } if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) { PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); currElements.add(new ResourceElement(method, bridgedMethod, pd)); } } } }); elements.addAll(0, currElements); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); return new InjectionMetadata(clazz, elements); } ``` 整個過程也比較簡單,解析出這個 Bean 帶有 `@Resource` 註解的所有欄位(或方法),構建成對應的 ResourceElement 物件,然後再構建成一個 InjectionMetadata 注入元資訊物件 #### postProcessProperties 方法 `postProcessProperties(PropertyValues pvs, Object bean, String beanName)` 方法,根據 `@Resource` 註解標註的欄位(或方法)的元資訊進行**依賴注入**,如下: ```java 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; } ``` 先找到這個 Bean 的注入元資訊物件,上面已經講過了,然後呼叫其 `inject(...)` 方法,該物件上面已經講過了,實際就是呼叫其內部 InjectedElement 的 `inject(...)` 方法 #### postProcessBeforeInitialization 方法 初始化 Bean 的時候會先執行 `@PostConstruct` 標註的初始化方法 ```java // InitDestroyAnnotationBeanPostProcessor.java @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // 找到 @PostConstruct 和 @PreDestroy 註解標註的方法們所對應的 LifecycleMetadata 物件 LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass()); try { // 執行 @PostConstruct 標註的初始化方法 metadata.invokeInitMethods(bean, beanName); } catch (InvocationTargetException ex) { throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException()); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Failed to invoke init method", ex); } return bean; } // InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata public void invokeInitMethods(Object target, String beanName) throws Throwable { Collection checkedInitMethods = this.checkedInitMethods; Collection initMethodsToIterate = (checkedInitMethods != null ? checkedInitMethods : this.initMethods); if (!initMethodsToIterate.isEmpty()) { for (LifecycleElement element : initMethodsToIterate) { if (logger.isTraceEnabled()) { logger.trace("Invoking init method on bean '" + beanName + "': " + element.getMethod()); } element.invoke(target); } } } ``` #### postProcessBeforeDestruction 方法 銷燬 Bean 的時候先執行 `@PreDestroy` 註解標註的銷燬方法 ```java // InitDestroyAnnotationBeanPostProcessor.java @Override public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException { // 找到 @PostConstruct 和 @PreDestroy 註解標註的方法們所對應的 LifecycleMetadata 物件 LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass()); try { // 執行 @PreDestroy 標註的銷燬方法 metadata.invokeDestroyMethods(bean, beanName); } catch (InvocationTargetException ex) { String msg = "Destroy method on bean with name '" + beanName + "' threw an exception"; if (logger.isDebugEnabled()) { logger.warn(msg, ex.getTargetException()); } else { logger.warn(msg + ": " + ex.getTargetException()); } } catch (Throwable ex) { logger.warn("Failed to invoke destroy method on bean with name '" + beanName + "'", ex); } } // InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata public void invokeDestroyMethods(Object target, String beanName) throws Throwable { Collection checkedDestroyMethods = this.checkedDestroyMethods; Collection destroyMethodsToUse = (checkedDestroyMethods != null ? checkedDestroyMethods : this.destroyMethods); if (!destroyMethodsToUse.isEmpty()) { for (LifecycleElement element : destroyMethodsToUse) { if (logger.isTraceEnabled()) { logger.trace("Invoking destroy method on bean '" + beanName + "': " + element.getMethod()); } element.invoke(target); } } } ``` ### ResourceElement CommonAnnotationBeanPostProcessor 的私有內部類,@Resource 注入欄位(或方法)物件 #### 構造方法 ```java protected abstract class LookupElement extends InjectionMetadata.InjectedElement { /** Bean 的名稱 */ protected String name = ""; /** 是否為預設的名稱(通過註解定義的) */ protected boolean isDefaultName = false; /** Bean 的型別 */ protected Class lookupType = Object.class; @Nullable protected String mappedName; public LookupElement(Member member, @Nullable PropertyDescriptor pd) { super(member, pd); } public final DependencyDescriptor getDependencyDescriptor() { if (this.isField) { return new LookupDependencyDescriptor((Field) this.member, this.lookupType); } else { return new LookupDependencyDescriptor((Method) this.member, this.lookupType); } } } private class ResourceElement extends LookupElement { /** 是否延遲載入 */ private final boolean lazyLookup; public ResourceElement(Member member, AnnotatedElement ae, @Nullable PropertyDescriptor pd) { super(member, pd); Resource resource = ae.getAnnotation(Resource.class); String resourceName = resource.name(); Class resourceType = resource.type(); this.isDefaultName = !StringUtils.hasLength(resourceName); if (this.isDefaultName) { resourceName = this.member.getName(); if (this.member instanceof Method && resourceName.startsWith("set") && resourceName.length() > 3) { resourceName = Introspector.decapitalize(resourceName.substring(3)); } } else if (embeddedValueResolver != null) { resourceName = embeddedValueResolver.resolveStringValue(resourceName); } if (Object.class != resourceType) { checkResourceType(resourceType); } else { // No resource type specified... check field/method. resourceType = getResourceType(); } this.name = (resourceName != null ? resourceName : ""); this.lookupType = resourceType; String lookupValue = resource.lookup(); this.mappedName = (StringUtils.hasLength(lookupValue) ? lookupValue : resource.mappedName()); Lazy lazy = ae.getAnnotation(Lazy.class); this.lazyLookup = (lazy != null && lazy.value()); } } ``` ResourceElement 的構造方法會通過 `@Resource` 註解和該欄位(或方法)解析出基本資訊 可以看到還繼承了 InjectionMetadata 的靜態內部類 InjectedElement,我們先來看到這個類的 `inject(...)` 方法 #### inject 方法 ```java public abstract static class InjectedElement { protected final Member member; protected final boolean isField; 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 { if (checkPropertySkipping(pvs)) { return; } try { Method method = (Method) this.member; ReflectionUtils.makeAccessible(method); method.invoke(target, getResourceToInject(target, requestingBeanName)); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } } @Nullable protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) { return null; } } ``` 不管是欄位還是方法,底層都是通過反射機制進行賦值或者呼叫,都會呼叫 `getResourceToInject(...)` 方法獲取到欄位值或者方法引數 #### getResourceToInject 方法 ```java @Override protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) { return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) : getResource(this, requestingBeanName)); } ``` 如果是延遲載入,則呼叫 `buildLazyResourceProxy(...)` 方法返回一個代理物件,如下: ```java protected Object buildLazyResourceProxy(final LookupElement element, final @Nullable String requestingBeanName) { TargetSource ts = new TargetSource() { @Override public Class getTargetClass() { return element.lookupType; } @Override public boolean isStatic() { return false; } @Override public Object getTarget() { return getResource(element, requestingBeanName); } @Override public void releaseTarget(Object target) { } }; ProxyFactory pf = new ProxyFactory(); pf.setTargetSource(ts); if (element.lookupType.isInterface()) { pf.addInterface(element.lookupType); } ClassLoader classLoader = (this.beanFactory instanceof ConfigurableBeanFactory ? ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() : null); return pf.getProxy(classLoader); } ``` 否則,呼叫 `getResource(...)` 方法獲取注入物件 #### getResource 方法 ```java protected Object getResource(LookupElement element, @Nullable String requestingBeanName) throws NoSuchBeanDefinitionException { if (StringUtils.hasLength(element.mappedName)) { return this.jndiFactory.getBean(element.mappedName, element.lookupType); } if (this.alwaysUseJndiLookup) { return this.jndiFactory.getBean(element.name, element.lookupType); } if (this.resourceFactory == null) { throw new NoSuchBeanDefinitionException(element.lookupType, "No resource factory configured - specify the 'resourceFactory' property"); } return autowireResource(this.resourceFactory, element, requestingBeanName); } ``` 前面的判斷忽略掉,直接看到最後會呼叫 `autowireResource(...)` 方法,並返回注入資訊 #### autowireResource 方法 ```java protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName) throws NoSuchBeanDefinitionException { Object resource; Set autowiredBeanNames; String name = element.name; if (factory instanceof AutowireCapableBeanFactory) { AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory; DependencyDescriptor descriptor = element.getDependencyDescriptor(); if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) { autowiredBeanNames = new LinkedHashSet<>(); resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null); if (resource == null) { throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object"); } } else { resource = beanFactory.resolveBeanByName(name, descriptor); autowiredBeanNames = Collections.singleton(name); } } else { resource = factory.getBean(name, element.lookupType); autowiredBeanNames = Collections.singleton(name); } if (factory instanceof ConfigurableBeanFactory) { ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory; for (String autowiredBeanName : autowiredBeanNames) { if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) { beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName); } } } return resource; } ``` `@Resource` 註解相比於 `@Autowired` 註解的處理更加複雜點,不過我們這裡可以看到也會呼叫 `DefaultListableBeanFactory#resolveDependency(...)` 方法,找到對應的注入物件,該方法在後面進行分析 ### 1. resolveDependency 處理依賴方法 `resolveDependency(DependencyDescriptor descriptor, String requestingBeanName, Set autowiredBeanNames, TypeConverter typeConverter)` 方法,找到對應的依賴 Bean,該方法在[**《Bean 的建立過程》**](https://www.cnblogs.com/lifullmoon/p/14452842.html)中也提到了,獲取 Bean 的例項物件時,構造器注入的引數也是通過該方法獲取的,本文的依賴注入底層也是通過該方法實現的,這裡我們對該方法一探究竟 ```java // DefaultListableBeanFactory.java @Override @Nullable public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { // <1> 設定引數名稱探測器,例如通過它獲取方法引數的名稱 descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); // <2> 如果依賴型別為 Optional 型別 if (Optional.class == descriptor.getDependencyType()) { // 呼叫 `createOptionalDependency(...)` 方法,先將 `descriptor` 注入表述器封裝成 NestedDependencyDescriptor 物件 // 底層處理和下面的 `5.2` 相同 return createOptionalDependency(descriptor, requestingBeanName); } // <3> 否則,如果依賴型別為 ObjectFactory 或 ObjectProvider 型別 else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) { // 返回一個 DependencyObjectProvider 私有內部類物件,並沒有獲取到例項的 Bean,需要呼叫其 getObject() 方法獲取目標物件 return new DependencyObjectProvider(descriptor, requestingBeanName); } // <4> 否則,如果依賴型別為 javax.inject.Provider 型別 else if (javaxInjectProviderClass == descriptor.getDependencyType()) { // 返回一個 Jsr330Provider 私有內部類物件,該物件也繼承 DependencyObjectProvider return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName); } // <5> 否則,通用的處理邏輯 else { // <5.1> 先通過 AutowireCandidateResolver 嘗試獲取一個代理物件,延遲依賴注入則會返回一個代理物件 Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName); // <5.2> 如果上面沒有返回代理物件,則進行處理,呼叫 `doResolveDependency(...)` 方法 if (result == null) { result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); } return result; } } ``` 過程如下: 1. 設定引數名稱探測器,例如通過它獲取方法引數的名稱 2. 如果依賴型別為 Optional 型別,則呼叫 `createOptionalDependency(...)` 方法,先將 `descriptor` 注入表述器封裝成 NestedDependencyDescriptor 物件,底層處理和下面的 `5.2` 相同 3. 否則,如果依賴型別為 ObjectFactory 或 ObjectProvider 型別,直接返回一個 `DependencyObjectProvider` 私有內部類物件,並沒有獲取到例項的 Bean,需要呼叫其 getObject() 方法獲取目標物件 4. 否則,如果依賴型別為 javax.inject.Provider 型別,直接返回一個 `Jsr330Provider` 私有內部類物件,該物件也繼承 DependencyObjectProvider 5. 否則,通用的處理邏輯 1. 先通過 AutowireCandidateResolver 嘗試獲取一個代理物件,延遲依賴注入則會返回一個代理物件 2. 如果上面沒有返回代理物件,則進行處理,呼叫 `doResolveDependency(...)` 方法 我們需要關注的是上面的第 `5.2` 步所呼叫 `doResolveDependency(...)` 方法,這一步是底層實現 ### 2. doResolveDependency 底層處理依賴方法 ```java // DefaultListableBeanFactory.java @Nullable public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { // 設定當前執行緒的注入點,並返回上次的注入點,屬於巢狀注入的一個保護點 InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor); try { // <1> 針對給定的工廠給定一個快捷實現的方式,暫時忽略 // 例如考慮一些預先解析的資訊,在進入所有 Bean 的常規型別匹配演算法之前,解析演算法將首先嚐試通過此方法解析快捷方式 Object shortcut = descriptor.resolveShortcut(this); if (shortcut != null) { // 返回快捷的解析資訊 return shortcut; } // 依賴的型別 Class type = descriptor.getDependencyType(); // <2> 獲取註解中的 value 對應的值,例如 @Value、@Qualifier 註解配置的 value 屬性值,注意 @Autowired 沒有 value 屬性配置 Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); if (value != null) { if (value instanceof String) { // <2.1> 解析註解中的 value,因為可能是佔位符,需要獲取到相應的資料 String strVal = resolveEmbeddedValue((String) value); BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null); value = evaluateBeanDefinitionString(strVal, bd); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); try { // <2.2> 進行型別轉換,並返回 return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor()); } catch (UnsupportedOperationException ex) { // A custom TypeConverter which does not support TypeDescriptor resolution... return (descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter())); } } // <3> 解析複合的依賴物件(Array、Collection、Map 型別),獲取該屬性元素型別的 Bean 們 // 底層和第 `4` 原理一樣,這裡會將 `descriptor` 封裝成 MultiElementDescriptor 型別 Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter); if (multipleBeans != null) { return multipleBeans; } // <4> 查詢與型別相匹配的 Bean 們 // 返回結果:key -> beanName;value -> 對應的 Bean Map matchingBeans = findAutowireCandidates(beanName, type, descriptor); // <5> 如果一個都沒找到 if (matchingBeans.isEmpty()) { // <5.1> 如果 @Autowired 配置的 required 為 true,表示必須,則丟擲異常 if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } // <5.2> 否則,返回一個空物