成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

揭秘 @Autowired 自動裝配原理與實現機制

開發 前端
在Java開發中,Spring框架憑借強大的依賴注入(Dependency Injection,DI)功能極大地提升了代碼的可維護性和可擴展性。其中,@Autowired注解作為Spring實現依賴注入的核心手段之一,被開發者廣泛使用。

前言

在Java開發中,Spring框架憑借強大的依賴注入(Dependency Injection,DI)功能極大地提升了代碼的可維護性和可擴展性。其中,@Autowired注解作為Spring實現依賴注入的核心手段之一,被開發者廣泛使用。

但@Autowired究竟是如何實現自動裝配的呢?本文將深入剖析其原理與實現機制,揭開它的神秘面紗。

自動裝配的核心流程

啟動容器時的掃描與解析

當Spring容器啟動時,會根據配置(如XML 配置或注解配置)掃描指定包路徑下的類。對于被@Component、@Service、@Repository、@Controller等注解標注的類,Spring會將其注冊為Bean,并存儲在容器的BeanDefinition注冊表中。在這個過程中,如果遇到帶有@Autowired注解的字段、方法或構造函數,會記錄下依賴關系信息。

實例化與依賴注入

在創建Bean實例時,Spring會根據BeanDefinition中的信息,首先實例化Bean(對于單例Bean,只會實例化一次)。在實例化完成后,Spring會處理@Autowired注解。對于字段上的@Autowired,Spring會在容器中查找與字段類型匹配的Bean。查找過程中,會優先按照類型匹配,如果存在多個同類型的Bean,則會根據字段名或使用@Qualifier注解指定的名稱進一步篩選。找到匹配的Bean后,將其注入到對應字段。

循環依賴處理

圖片圖片

在自動裝配過程中,可能會遇到循環依賴的情況,即兩個或多個Bean之間相互依賴。Spring容器通過三級緩存機制來處理循環依賴問題。一級緩存存儲完全初始化好的Bean;二級緩存存儲早期暴露的Bean(尚未完成屬性填充和初始化);三級緩存存儲Bean 的創建工廠。當檢測到循環依賴時,Spring會從二級緩存中獲取早期暴露的Bean,避免因循環依賴導致的死循環問題。

Bean的初始化過程

Spring的可以分為5個小的階段:實例化、初始化、注冊Destruction回調、Bean的正常使用以及Bean的銷毀。

圖片圖片

  • 實例化(Instantiation):
  • 實例化是創建對象的過程。在Spring中,這通常指的是通過調用類的構造器來創建Bean的實例。這是對象生命周期的開始階段。對應doCreateBean中的createBeanInstance方法。
  • 初始化(Initialization):
  • 初始化是在Bean實例創建后,進行一些設置或準備工作的過程。在Spring中,包括設置Bean的屬性,調用各種前置&后置處理器。對應doCreateBean中的populateBean和initializeBean方法。

自動裝配其實發生在Instantiation -> Populate -> Initialization的過程中,屬于Bean的生命周期中的populate階段。

  • 在實例化Bean的時候在createBeanInstance方法中會調用 AutowiredAnnotationBeanPostProcessor中的方法來獲取需要自動注入的構造方法,AutowiredAnnotationBeanPostProcessor的方法來完成對所有需要自動注入的屬性和方法的解析和緩存。
  • populatedBean方法中調用到AutowiredAnnotationBeanPostProcessor中的方法來完成需要自動注入屬性的注入工作。
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    // 獲取Bean定義中的屬性值    
    PropertyValues pvs = mbd.getPropertyValues();
    // 如果BeanWrapper為空,則無法設置屬性值    
    if (bw == null) {
        if (!pvs.isEmpty()) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        } else {
            // 對于null實例,跳過設置屬性階段            
            return;
        }
    }
    // 在設置屬性之前,給InstantiationAwareBeanPostProcessors機會修改Bean狀態    
    // 這可以用于支持字段注入等樣式    
    boolean continueWithPropertyPopulation = true;
    // 如果Bean不是合成的,并且存在InstantiationAwareBeanPostProcessor,執行后續處理    
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    continueWithPropertyPopulation = false;
                    break;
                }
            }
        }
    }
    // 如果上述處理后決定不繼續,則返回    
    if (!continueWithPropertyPopulation) {
        return;
    }
    // 根據自動裝配模式(按名稱或類型),設置相關的屬性值    
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        // 如果是按名稱自動裝配,添加相應的屬性值        
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }
        // 如果是按類型自動裝配,添加相應的屬性值        
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }
        pvs = newPvs;
    }
    // 檢查是否需要進行依賴性檢查    
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
    // 如果需要,則進行依賴性檢查    
    if (hasInstAwareBpps || needsDepCheck) {
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        if (hasInstAwareBpps) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvs == null) {
                        return;
                    }
                }
            }
        }
        if (needsDepCheck) {
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }
    }
    // 應用屬性值    
    applyPropertyValues(beanName, mbd, bw, pvs);
}

@Autowired 實現的關鍵源碼解析

@Autowired注解的實現主要涉及到AutowiredAnnotationBeanPostProcessor類,它繼承自InstantiationAwareBeanPostProcessorAdapter(后期被棄用,改實現SmartInstantiationAwareBeanPostProcessor),該類實現了postProcessProperties方法,用于處理Bean的屬性注入。

@Override
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;
}

在postProcessProperties方法中,首先通過findAutowiringMetadata方法獲取與@Autowired相關的元數據(包括要注入的字段、方法等信息),然后調用metadata.inject方法進行實際的依賴注入操作。metadata.inject方法會遍歷需要注入的元素,通過反射機制獲取對應的Bean并完成注入。

總結

如果你在面試中遇到這個問題,可以這樣回答:

  1. @Autowired是Spring提供的自動裝配注解,它通過AutowiredAnnotationBeanPostProcessor實現依賴注入。
  2. 這個處理器在Bean初始化階段介入,掃描字段或方法的注解,找到需要注入的地方,然后根據類型從容器中查找Bean,通過反射完成注入。
  3. 如果存在多個實現,可以通過@Qualifier或@Primary來指定注入對象。構造器注入則在實例化時完成,推薦用于強依賴場景。
責任編輯:武曉燕 來源: 一安未來
相關推薦

2025-01-14 10:09:43

硬中斷Linux系統

2022-08-08 07:33:11

自動裝配Java容器

2024-12-25 16:01:01

2012-11-28 10:37:25

Linux集群安裝配置

2020-09-22 08:52:50

平臺實現消息

2011-06-13 10:21:25

QT 信號 槽機制

2010-04-29 10:11:07

Linux集群

2025-05-27 01:00:00

2021-07-19 09:25:19

數據庫MySQL技術

2022-04-08 08:32:40

mobx狀態管理庫redux

2024-10-10 17:46:06

2012-02-17 10:50:10

Java

2024-10-10 12:12:45

SpringAI版本

2010-08-06 10:15:35

Flex綁定

2010-08-06 09:45:50

Flex事件機制

2021-05-13 23:30:17

JavaScript 原理揭秘

2009-09-04 10:37:50

Java堆棧溢出

2020-02-25 16:48:35

AndroidGoogle 移動系統

2015-03-27 09:50:37

2021-12-20 00:03:38

Webpack運行機制
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 成人在线视频免费看 | 国产一区二区三区四区三区四 | av在线一区二区三区 | 久久一| 丁香五月网久久综合 | 在线一区视频 | 日韩欧美二区 | 亚洲国产中文字幕 | 欧美不卡网站 | 欧美福利在线 | 欧美日韩一区二区在线 | 久久69精品久久久久久国产越南 | 欧美日韩亚洲三区 | 日本三级电影在线观看视频 | 日韩中文在线观看 | 在线视频h | 成人在线精品视频 | 国产精品久久久久久福利一牛影视 | 国产精品久久久久久久白浊 | 午夜成人在线视频 | 欧洲性生活视频 | 国产高清视频在线观看 | 91精品国产综合久久久久 | 国产精久久久久久久 | 欧美精品一区二区三区在线播放 | 亚洲人人舔人人 | 欧美久久久久久 | www.日韩在线 | 国产日韩电影 | 欧洲精品在线观看 | 日韩av一区二区在线观看 | 亚洲精品国产第一综合99久久 | 亚洲电影成人 | 亚洲精品粉嫩美女一区 | 97精品超碰一区二区三区 | 色综合色综合色综合 | 国产精品视频在线播放 | 亚洲国产成人在线 | 一区二区伦理电影 | 在线91 | 欧洲精品码一区二区三区免费看 |