@Autowired 註解詳解

前言

我們平時使用 Spring 時,想要 依賴注入 時使用最多的是 @Autowired 註解了,本文主要講解 Spring 是如何處理該註解並實現 依賴注入 的功能的。

正文

首先我們看一個測試用例:

User 實體類:

public class User {

    private Long id;
    private String name;

	// 省略 get 和 set 方法
}

測試類:

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 createBean 方法詳解 一文中有介紹過。下面我們看一下 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 中跟屬性注入有關的方法有兩個:postProcessMergedBeanDefinitionpostProcessPropertyValues

前者是 MergedBeanDefinitionPostProcessor 接口中的方法,定義如下:

public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {

	/**
	 * 對指定bean的BeanDefinition合併后的處理方法回調
	 */
	void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

	/**
	 * @since 5.1
	 * 通知已重新設置指定beanName的BeanDefinition,如果實現該方法應該清除受影響的bean的所有元數據
	 */
	default void resetBeanDefinition(String beanName) {
	}

}

後者是 InstantiationAwareBeanPostProcessor 接口中的方法,定義如下:

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

	/**
	 * Bean 實例化前調用,返回非 {@code null} IoC 容器不會對 Bean 進行實例化 並且後續的生命周期回調方	  *	法不會調用,返回 {@code null} 則進行 IoC 容器對 Bean 的實例化
	 */
	@Nullable
	default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		return null;
	}

	/**
	 * Bean 實例化之後,屬性填充之前調用,返回 {@code true} 則進行默認的屬性填充步驟,返回 {@code 		 * false} 會跳過屬性填充階段。
	 */
	default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
		return true;
	}

	/**
	 * Bean 實例化后屬性賦值前調用,PropertyValues 是已經封裝好的設置的屬性值,返回 {@code null} 繼續
	 * 使用現有屬性,否則會替換 PropertyValues。
	 * @since 5.1版本新加的和底下的方法一樣
	 */
	@Nullable
	default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
			throws BeansException {
		return null;
	}

	/**
	 * 跟上面方法一樣的功能,只不過是5.1以前版本所使用的
	 * 返回 {@code null} 會跳過屬性填充階段
	 */
	@Deprecated
	@Nullable
	default PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

		return pvs;
	}

}

關於這兩個方法的調用時機,可以查看 Spring IoC createBean 方法詳解。

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) {
    // 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);
    // 判斷是否需要刷新,即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 緩存中,便於後續使用。

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 createBean 方法詳解 一文中有介紹過,這裏不再贅述;同樣 registerDependentBeans() 最終會調用 DefaultSingletonBeanRegistry.registerDependentBean() ,該方法在 Spring IoC getBean 方法詳解 一文中有介紹過,這裏也不再贅述。

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) {
        // Shortcut for avoiding synchronization...
        // 如果緩存過,直接調用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 createBean 方法詳解 一文中有介紹過,這裏就不再贅述了。

總結

本文主要介紹了 Spring 對 @Autowired 註解的主要處理過程,結合前面的 Spring IoC getBean 方法詳解 和 Spring IoC createBean 方法詳解 文章一起看才能更好的理解。

最後,我模仿 Spring 寫了一個精簡版,代碼會持續更新。地址:https://github.com/leisurexi/tiny-spring。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

您可能也會喜歡…