前言
本系列所有基於 Spring 5.2.2.BUILD-SNAPSHOT
版本。由於 Spring 整個體系太過於龐大,因此只會進行關鍵部分的源碼解析。html
咱們平時使用 Spring 時,想要 依賴注入 時使用最多的是 @Autowired
註解了,本文主要講解 Spring 是如何處理該註解並實現 依賴注入 的功能。java
正文
首先咱們看一個測試用例:git
User
實體類:github
public class User { private Long id; private String name; // 省略 get 和 set 方法 }
測試類:spring
public class AnnotationDependencyInjectTest { /** * @Autowired 字段注入 */ @Autowired private User user; private City city; /** * @Autowired 方法注入 */ @Autowired public void initCity(City city) { this.city = city; } public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(AnnotationDependencyInjectTest.class); context.refresh(); AnnotationDependencyInjectTest bean = context.getBean(AnnotationDependencyInjectTest.class); // @Autowired 字段注入 System.out.println(bean.user); // @Autowired 方法注入 System.out.println(bean.city); UserHolder userHolder = context.getBean(UserHolder.class); // @Autowired 構造器注入 System.out.println(userHolder.getUser()); context.close(); } @Bean public User user() { User user = new User(); user.setId(1L); user.setName("leisurexi"); return user; } @Bean public City city() { City city = new City(); city.setId(1L); city.setName("北京"); return city; } /** * @Autowired 構造函數注入 */ static class UserHolder { private User user; @Autowired public UserHolder(User user) { this.user = user; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } } }
上面分別展現了 @Autowired
註解的字段注入和方法注入,下面咱們開始分析 Spring 是如何實現的。數組
首先使 @Autowired
註解生效的一個關鍵類是 AutowiredAnnotationBeanPostProcessor
,該類實現了 InstantiationAwareBeanPostProcessorAdapter
抽象類;該抽象類就是一個適配器的做用提供了接口方法的默認實現,InstantiationAwareBeanPostProcessorAdapter
又實現了 SmartInstantiationAwareBeanPostProcessor
接口,同時實現該接口的 determineCandidateConstructors()
方法能夠指定 bean
的候選構造函數;而後 SmartInstantiationAwareBeanPostProcessor
接口又繼承了 InstantiationAwareBeanPostProcessor
接口,該接口提供了 bean
實例化先後的生命週期回調以及屬性賦值前的後置處理方法,@Autowired
註解的屬性注入就是經過重寫該接口的 postProcessProperties()
實現的。這兩個接口都在 Spring IoC bean 的建立 一文中有介紹過。下面咱們看一下 AutowiredAnnotationBeanProcessor
的繼承關係圖:緩存
關於 AutowiredAnnotationBeanPostProcessor
這個後置處理器是怎麼加入到 beanFactory
中的,咱們在 Spring IoC component-scan 節點詳解 一文中介紹過主要是經過 AnnotationConfigUtils#registerAnnotationConfigProcessors()
實現的。多線程
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) { // 省略其餘代碼... // 註冊用於處理@Autowired、@Value、@Inject註解的後置處理器 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)); } // 省略其餘代碼... }
屬性和方法注入
AutowiredAnnotationBeanPostProcessor
中跟屬性注入有關的方法有兩個:postProcessMergedBeanDefinition
和 postProcessPropertyValues
。併發
前者是 MergedBeanDefinitionPostProcessor
接口中的方法,定義以下:函數
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor { /** * 對指定bean的BeanDefinition合併後的處理方法回調 */ void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName); // 省略其餘代碼... }
後者是 InstantiationAwareBeanPostProcessor
接口中的方法,定義以下:
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { /** * Bean 實例化後屬性賦值前調用,PropertyValues 是已經封裝好的設置的屬性值,返回 {@code null} 繼續 * 使用現有屬性,不然會替換 PropertyValues。 */ @Nullable default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { return null; } // 省略其餘代碼... }
關於這兩個方法的調用時機,能夠查看Spring IoC bean 的建立和Spring IoC 屬性賦值階段。
bean 合併後處理
AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
首先執行的是 postProcessMergedBeanDefinition()
方法。
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { // 尋找須要注入的字段或方法,並封裝成 InjectionMetadata,見下文詳解 InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null); // 檢查元數據中的註解信息 metadata.checkConfigMembers(beanDefinition); }
InjectionMetadata
就是注入的元信息描述,主要字段以下:
public class InjectionMetadata { // 須要依賴注入的目標類 private final Class<?> targetClass; // 注入元素的集合 private final Collection<InjectedElement> injectedElements; // 忽略其它代碼 }
InjectedElement
就是注入的元素,主要字段以下:
public abstract static class InjectedElement { // 注入的屬性或方法 protected final Member member; // 須要注入的是不是字段 protected final boolean isField; }
查找須要注入的字段或方法
AutowiredAnnotationBeanPostProcessor#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); // 判斷是否須要刷新,即metadata爲null或者metadata中存儲的targetClass和當前clazz不等 if (InjectionMetadata.needsRefresh(metadata, clazz)) { // 這裏至關因而一個double check,防止多線程出現的併發問題 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; }
建立須要注入的元信息
AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) { if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) { return InjectionMetadata.EMPTY; } // 判斷當前類或其字段或其方法是否標註了autowiredAnnotationTypes中的註解,沒有的話直接返回空的 List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); Class<?> targetClass = clazz; do { final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>(); // 遍歷targetClass中的字段 ReflectionUtils.doWithLocalFields(targetClass, field -> { // 獲取field上的@Autowired註解信息 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; } // 獲取@Autowired註解中的required屬性 boolean required = determineRequiredStatus(ann); // 將裝成AutowiredFieldElement添加進currElements currElements.add(new AutowiredFieldElement(field, required)); } }); // 遍歷targetClass中的方法 ReflectionUtils.doWithLocalMethods(targetClass, method -> { // 找到橋接方法 Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); // 判斷方法的可見性,若是不可見則直接返回 if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } // 獲取method上的@Autowired註解信息 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); } } // 獲取@Autowired註解中的required屬性 boolean required = determineRequiredStatus(ann); // 將方法和目標類型封裝成屬性描述符 PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); // 封裝成AutowiredMethodElement添加進currElements currElements.add(new AutowiredMethodElement(method, required, pd)); } }); // 將currElements整個添加進elements elements.addAll(0, currElements); // 獲取targetClass的父類,進行下一次循環 targetClass = targetClass.getSuperclass(); } // 當targetClass爲空或者targetClass等於Object.class時會退出循環 while (targetClass != null && targetClass != Object.class); // 將elements和clazz封裝成InjectionMetadata返回 return InjectionMetadata.forElements(elements, clazz); }
上面代碼中的 findAutowiredAnnotation()
就是在遍歷 autowiredAnnotationTypes
屬性,看字段或者方法上的註解是否存在於 autowiredAnnotationTypes
中,或者其派生註解,找到第一個就返回,不會再繼續遍歷了。
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware { private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4); public AutowiredAnnotationBeanPostProcessor() { this.autowiredAnnotationTypes.add(Autowired.class); this.autowiredAnnotationTypes.add(Value.class); try { this.autowiredAnnotationTypes.add((Class<? extends Annotation>) 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. } } }
從 AutowiredAnnotationBeanPostProcessor
類的構造函數中,咱們能夠發現 autowiredAnnotationTypes
默認添加了 @Autowired
、@Value
以及 @Inject
(在 JSR-330 的jar包存在於當前環境時)。
至此,使用 @Autowired
修飾的字段和方法已經封裝成 InjectionMetadata
並放在 injectionMetadataCache
緩存中,便於後續使用。
bean 屬性的後置處理
AutowireAnnotationBeanPostProcessor#postProcessProperties
postProcessMergedBeanDefinition()
調用後 bean
就會進行實例化接着調用 postProcessProperties()
。
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { // 獲取緩存中的 InjectionMetadata 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; } // InjectMetadata.java public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { // 獲取檢查後的元素 Collection<InjectedElement> checkedElements = this.checkedElements; // 若是checkedElements不爲空就使用checkedElements,不然使用injectedElements Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements); if (!elementsToIterate.isEmpty()) { // 遍歷elementsToIterate for (InjectedElement element : elementsToIterate) { if (logger.isTraceEnabled()) { logger.trace("Processing injected element of bean '" + beanName + "': " + element); } // AutowiredFieldElement、AutowiredMethodElement這兩個類繼InjectionMetadata.InjectedElement // 各自重寫了inject方法 element.inject(target, beanName, pvs); } } }
字段注入
AutowiredFieldElement#inject
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { // 強轉成Field類型 Field field = (Field) this.member; Object value; if (this.cached) { // 若是緩存過,直接使用緩存的值,通常第一次注入都是false value = resolvedCachedArgument(beanName, this.cachedFieldValue); } else { // 構建依賴描述符 DependencyDescriptor desc = new DependencyDescriptor(field, this.required); desc.setContainingClass(bean.getClass()); Set<String> autowiredBeanNames = new LinkedHashSet<>(1); Assert.state(beanFactory != null, "No BeanFactory available"); // 獲取類型轉換器 TypeConverter typeConverter = beanFactory.getTypeConverter(); try { // 進行依賴解決,獲取符合條件的bean value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); } // 加鎖 synchronized (this) { // 若是沒有被緩存 if (!this.cached) { // 找到了須要的bean || 該字段是必要的 if (value != null || this.required) { // 將依賴描述符賦值給cachedFieldValue this.cachedFieldValue = desc; // 註冊bean的依賴關係,用於檢測是否循環依賴 registerDependentBeans(beanName, autowiredBeanNames); // 若是符合條件的bean只有一個 if (autowiredBeanNames.size() == 1) { String autowiredBeanName = autowiredBeanNames.iterator().next(); // beanFactory含有名爲autowiredBeanName的bean && 類型是匹配的 if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { // 將該屬性解析到的bean的信息封裝成ShortcutDependencyDescriptor // 以後能夠經過調用resolveShortcut()來間接調beanFactory.getBean()快速獲取bean this.cachedFieldValue = new ShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType()); } } } else { this.cachedFieldValue = null; } // 緩存標識設置爲true this.cached = true; } } } // 若是找到了符合的bean,設置字段可訪問,利用反射設置值 if (value != null) { ReflectionUtils.makeAccessible(field); field.set(bean, value); } }
上面代碼中的 beanFactory.resolveDependency()
在 Spring IoC bean 的建立 一文中有介紹過,這裏再也不贅述;一樣 registerDependentBeans()
最終會調用 DefaultSingletonBeanRegistry.registerDependentBean()
,該方法在 Spring IoC bean 的建立 一文中有介紹過,這裏也再也不贅述。
方法注入
AutowiredMethodElement#inject
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { // 檢查是否須要跳過 if (checkPropertySkipping(pvs)) { return; } // 強轉成Method類型 Method method = (Method) this.member; Object[] arguments; if (this.cached) { // 若是緩存過,直接調用beanFactory.resolveDependency()返回符合的bean arguments = resolveCachedArguments(beanName); } else { // 獲取參數數量 int argumentCount = method.getParameterCount(); arguments = new Object[argumentCount]; // 建立依賴描述符數組 DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount]; // 記錄用於自動注入bean的名稱集合 Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount); Assert.state(beanFactory != null, "No BeanFactory available"); // 獲取類型轉換器 TypeConverter typeConverter = beanFactory.getTypeConverter(); // 遍歷參數 for (int i = 0; i < arguments.length; i++) { // 將方法和參數的下標構建成MethodParameter,這裏面主要記錄了參數的下標和類型 MethodParameter methodParam = new MethodParameter(method, i); // 將MethodParameter構建成DependencyDescriptor DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required); currDesc.setContainingClass(bean.getClass()); descriptors[i] = currDesc; try { // 進行依賴解決,找到符合條件的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); } } // 這裏跟字段注入差很少,就是註冊bean的依賴關係,而且緩存每一個參數的ShortcutDependencyDescriptor synchronized (this) { if (!this.cached) { if (arguments != null) { DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length); registerDependentBeans(beanName, autowiredBeans); if (autowiredBeans.size() == argumentCount) { Iterator<String> it = autowiredBeans.iterator(); Class<?>[] paramTypes = method.getParameterTypes(); 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; } } } // 找到了符合條件的bean if (arguments != null) { try { // 設置方法可訪問,利用反射進行方法調用,傳入參數 ReflectionUtils.makeAccessible(method); method.invoke(bean, arguments); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } }
構造器注入
構造器注入就是經過調用 determineCandidateConstructors()
來返回合適的構造器。
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName) throws BeanCreationException { // Quick check on the concurrent map first, with minimal locking. // 首先從緩存中獲取 Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass); // 緩存爲空 if (candidateConstructors == null) { // Fully synchronized resolution now... // 這裏至關於double check synchronized (this.candidateConstructorsCache) { candidateConstructors = this.candidateConstructorsCache.get(beanClass); if (candidateConstructors == null) { Constructor<?>[] rawCandidates; try { // 獲取beanClass的全部構造函數 rawCandidates = beanClass.getDeclaredConstructors(); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Resolution of declared constructors on bean Class [" + beanClass.getName() +"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex); } // 存放標註了@Autowired註解的構造器 List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length); // 存放標註了@Autowired註解,而且required爲true的構造器 Constructor<?> requiredConstructor = null; Constructor<?> defaultConstructor = null; for (Constructor<?> candidate : rawCandidates) { // 獲取構造器上的@Autowired註解信息 MergedAnnotation<?> ann = findAutowiredAnnotation(candidate); if (ann == null) { // 若是沒有從候選者找到註解,則嘗試解析beanClass的原始類(針對CGLIB代理) Class<?> userClass = ClassUtils.getUserClass(beanClass); if (userClass != beanClass) { try { Constructor<?> superCtor = userClass.getDeclaredConstructor(candidate.getParameterTypes()); ann = findAutowiredAnnotation(superCtor); } catch (NoSuchMethodException ex) { // Simply proceed, no equivalent superclass constructor found... } } } if (ann != null) { // 若是requiredConstructor不爲空,表明有多個標註了@Autowired且required爲true的構造器,此時Spring不知道選擇哪一個拋出異常 if (requiredConstructor != null) { throw new BeanCreationException(beanName, "Invalid autowire-marked constructor: " + candidate +". Found constructor with 'required' Autowired annotation already: " + requiredConstructor); } // 獲取@Autowired註解的reuired屬性的值 boolean required = determineRequiredStatus(ann); if (required) { // 若是當前候選者是@Autowired(required = true),則以前不能存在其餘使用@Autowire註解的構造函數,不然拋異常 if (!candidates.isEmpty()) { throw new BeanCreationException(beanName,"Invalid autowire-marked constructors: " + candidates +". Found constructor with 'required' Autowired annotation: " + candidate); } // required爲true將當前構造器賦值給requiredConstructor requiredConstructor = candidate; } // 將當前構造器加入進候選構造器中 candidates.add(candidate); } // 沒有標註了@Autowired註解且參數長度爲0,賦值爲默認構造器 else if (candidate.getParameterCount() == 0) { defaultConstructor = candidate; } } // 有標註了@Autowired註解的構造器 if (!candidates.isEmpty()) { // Add default constructor to list of optional constructors, as fallback. // 沒有標註了@Autowired且required爲true的構造器 if (requiredConstructor == null) { // 默認構造器不爲空 if (defaultConstructor != null) { // 將默認構造器加入進候選構造器中 candidates.add(defaultConstructor); } } // 將候選者賦值給candidateConstructors candidateConstructors = candidates.toArray(new Constructor<?>[0]); } // 只有1個構造器 && 參數長度大於0(非默認構造器),只能用它當作候選者了 else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) { candidateConstructors = new Constructor<?>[] {rawCandidates[0]}; } // 只有1個構造器 && 參數長度大於0,只能用它當作候選者了 else if (nonSyntheticConstructors == 2 && primaryConstructor != null && defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) { candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor}; } else if (nonSyntheticConstructors == 1 && primaryConstructor != null) { candidateConstructors = new Constructor<?>[] {primaryConstructor}; } // 返回一個空的Constructor else { candidateConstructors = new Constructor<?>[0]; } // 緩存候選的構造器 this.candidateConstructorsCache.put(beanClass, candidateConstructors); } } } // 若是候選構造器長度大於0,直接返回,不然返回null return (candidateConstructors.length > 0 ? candidateConstructors : null); }
關於 SmartInstantiationAwareBeanPostProcessor
接口的調用時機,在 Spring IoC bean 的建立 一文中有介紹過,這裏就再也不贅述了。
總結
本文主要介紹了 Spring 對 @Autowired
註解的主要處理過程,結合前面的 Spring IoC bean 的加載 和 Spring IoC bean 的建立 以及 Spring IoC 屬性賦值階段 一塊兒看才能更好的理解。
最後,我模仿 Spring 寫了一個精簡版,代碼會持續更新。地址:https://github.com/leisurexi/tiny-spring。