@Autowired 注解由 Spring 的 org.springframework.beans.factory.annotation.Autowired 類定義, 直譯過來就是自動注入的意思。
@Autowired的定義如下:
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Autowired { boolean required() default true;}
將 @Autowired 直接應用于類的成員變量上。Spring 容器會自動為這些變量找到與其類型匹配的 Bean 實例,并進行注入。
public class MyClass { @Autowired private MyService myService;}
將 @Autowired 應用于類的構造函數上。
Spring 容器會自動解析構造函數的參數類型,并為這些參數找到與其類型匹配的 Bean 實例,然后注入到構造函數中。
public class MyClass { private MyService myService; @Autowired public MyClass(MyService myService) { this.myService = myService; }}
將 @Autowired 應用于類的方法上。
當類實例化時,Spring 容器會自動解析這些方法的參數類型,并為這些參數找到與其類型匹配的 Bean 實例,然后調用這些方法并注入參數。
public class MyClass { private MyService myService; @Autowired public void setMyService(MyService myService) { this.myService = myService; }}
需要注意的是,通過 @Autowired 注解實現依賴注入時,如果在 Spring 容器中找不到與某個依賴類型匹配的 Bean 實例(或者找到多個,但沒有明確的優先級),那么 Spring 將拋出異常。
除非將該注解的 required 屬性設置為 false,這樣在找不到匹配的 Bean 時,框架將不會拋出異常。
public class MyClass { @Autowired(required = false) private MyService myService;}
在 Spring 中,AutowiredAnnotationBeanPostProcessor (AABP) 負責處理帶有 @Autowired 注解的成員變量、Setter 方法。
以下是 AABP 解析 @Autowired 的完整代碼調用流程:
當 Spring 容器實例化一個 Bean 時,會創建相應的 BeanDefinition 對象。BeanDefinition 包含了關于 Bean 的所有元數據信息。
在容器實例化、配置和初始化 Bean 的過程中,它會調用 AABP 的 postProcessMergedBeanDefinition 方法,以收集與依賴注入相關的元數據。
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { 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; }
findAutowiringMetadata 方法會查找 Bean 的所有@Autowired 注解相關的元數據,并獲取 InjectionMetadata 對象, 如果該對象尚不存在,會創建一個新的對象。
protected InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { // ... (省略無關代碼) List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); Class<?> targetClass = clazz; // 遍歷 Bean 的類結構,從子類向基類查找有@Autowired 注解的字段、方法和構造器 do { final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>(); ReflectionUtils.doWithLocalFields(targetClass, field -> { // 尋找帶有@Autowired 注解的字段 MergedAnnotation<?> ann = findAutowiredAnnotation(field); if (ann != null) { if (Modifier.isStatic(field.getModifiers())) { // 靜態字段不能自動注入 // ... (省略錯誤處理和日志) } boolean required = determineRequiredStatus(ann); // AutowiredFieldElement 屬性Autowired元素 currElements.add(new AutowiredFieldElement(field, required)); } }); ReflectionUtils.doWithLocalMethods(targetClass, method -> { // 尋找帶有@Autowired 注解的Setter方法或普通方法 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())) { // 靜態方法不能自動注入 // ... (省略錯誤處理和日志) } PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); boolean required = determineRequiredStatus(ann); // AutowiredMethodElement 方法 Autowired 元素 currElements.add(new AutowiredMethodElement(method, required, pd)); } }); elements.addAll(0, currElements); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); // 構建并返回 InjectionMetadata 對象 return new InjectionMetadata(clazz, elements);}
上面的代碼中,我在關鍵位置添加了注釋,老鐵們可以仔細看一下,上述代碼的主要作用就是找到一個類中:
當依賴注入需要發生時,容器會調用 AABP 的 postProcessProperties 方法。
該方法中會調用 InjectionMetadata 的 inject 方法來實際注入 @Autowired 注解的成員變量、成員方法:
metadata.inject(bean, beanName, pvs);
最后,通過執行 AutowiredFieldElement 和 AutowiredMethodElement 的 inject 方法來實際注入屬性值和方法參數。
AutowiredFieldElement 的 inject 方法實現如下:
@Override protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Field field = (Field) this.member; Object value; if (this.cached) { try { value = resolvedCachedArgument(beanName, this.cachedFieldValue); } catch (NoSuchBeanDefinitionException ex) { // Unexpected removal of target bean for cached argument -> re-resolve value = resolveFieldValue(field, bean, beanName); } } else { value = resolveFieldValue(field, bean, beanName); } if (value != null) { ReflectionUtils.makeAccessible(field); field.set(bean, value); } }
AutowiredMethodElement 的 inject 方法的實現如下:
@Override protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { if (checkPropertySkipping(pvs)) { return; } Method method = (Method) this.member; Object[] arguments; if (this.cached) { try { arguments = resolveCachedArguments(beanName); } catch (NoSuchBeanDefinitionException ex) { // Unexpected removal of target bean for cached argument -> re-resolve arguments = resolveMethodArguments(method, bean, beanName); } } else { arguments = resolveMethodArguments(method, bean, beanName); } if (arguments != null) { try { ReflectionUtils.makeAccessible(method); method.invoke(bean, arguments); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } }
通過以上流程,AutowiredAnnotationBeanPostProcessor 將解析并注入帶有 @Autowired 注解的成員變量、方法。
本文鏈接:http://www.www897cc.com/showinfo-26-80864-0.html終于有人把Autowired注解講清楚了,贊!!!
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com