最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot中@Autowired生效方式詳解

 更新時間:2022年06月17日 10:19:38   作者:alonwang  
@Autowired注解可以用在類屬性,構(gòu)造函數(shù),setter方法和函數(shù)參數(shù)上,該注解可以準(zhǔn)確地控制bean在何處如何自動裝配的過程。在默認(rèn)情況下,該注解是類型驅(qū)動的注入

前言

@Component
public class SimpleBean3 {
    @Autowired
    private SimpleBean simpleBean;
}

@Autowired修飾的字段會被容器自動注入.那么Spring Boot中使如何實現(xiàn)這一功能呢? AutowiredAnnotationBeanPostProcessor!

BeanPostProcessor implementation that autowires annotated fields, setter methods, and arbitrary config methods. Such members to be injected are detected through annotations: by default, Spring's @Autowired and @Value annotations.
Also supports JSR-330's @Inject annotation, if available, as a direct alternative to Spring's own @Autowired.

AutowiredAnnotationBeanPostProcessor(以下簡稱AutowiredProcessor)間接實現(xiàn)了InstantiationAwareBeanPostProcessor接口.通過postProcessProperties(...)完成@Autowired的注入,本文將按照下圖流程梳理AutowiredProcessor的生效邏輯.

SpringBoot-autowired.png

正文

注冊AutowiredProcessor的BeanDefinition

SpringApplication#createApplicationContext默認(rèn)會創(chuàng)建 AnnotationConfigApplicationContext,而AnnotationConfigApplicationContext又會創(chuàng)建AnnotatedBeanDefinitionReader

    public AnnotationConfigApplicationContext() {
        this.reader = new AnnotatedBeanDefinitionReader(this);
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

AnnotatedBeanDefinitionReader構(gòu)造時會調(diào)用AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry),將AutowiredProcessor的BeanDefinition注冊到容器

    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, @Nullable Object source) {
        //忽略部分代碼...
        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));
        }
        //忽略部分代碼...
        return beanDefs;
    }

實例化AutowiredProcessor

在AbstractApplicationContext的refresh階段,會注冊并實例化所有的BeanPostProcessor

public void refresh() throws BeansException, IllegalStateException {
            //...忽略部分代碼
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);
                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);
                // ########### 這里注冊所有的BeanPostProcessor ##########  
                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);
                // Initialize message source for this context.
                initMessageSource();
                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();
                // Initialize other special beans in specific context subclasses.
                onRefresh();
                // Check for listener beans and register them.
                registerListeners();
                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);
                // Last step: publish corresponding event.
                finishRefresh()
            //...忽略部分代碼
    }

實際的注冊邏輯交給了PostProcessorRegistrationDelegate

    protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
    }

在PostProcessorRegistrationDelegate中,獲取到所有的BeanPostProcessor(基于BeanDefinition),并將其分為幾種類型,并按照不同的優(yōu)先級進行處理化,這塊不是這篇文章的重點,我們只需要知道在這里AutowiredProcessor被注冊就可以了.

創(chuàng)建bean時進行注入

以SimpleBean3的注入為例, 它是單例的,在AbstractApplicationContext.refresh()的finishBeanFactoryInitialization(beanFactory)時創(chuàng)建.

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        //...忽略部分代碼
        // Instantiate all remaining (non-lazy-init) singletons.
        beanFactory.preInstantiateSingletons();
    }

調(diào)用到了BeanFactory.preInstantiateSingletons(),走到getBean()邏輯

public void preInstantiateSingletons() throws BeansException {
        //...忽略部分代碼
        List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
        // Trigger initialization of all non-lazy singleton beans...
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                if (isFactoryBean(beanName)) {
                    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                    if (bean instanceof FactoryBean) {
                        final FactoryBean<?> factory = (FactoryBean<?>) bean;
                        boolean isEagerInit;
                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                            isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                            ((SmartFactoryBean<?>) factory)::isEagerInit,
                                    getAccessControlContext());
                        }
                        else {
                            isEagerInit = (factory instanceof SmartFactoryBean &&
                                    ((SmartFactoryBean<?>) factory).isEagerInit());
                        }
                        if (isEagerInit) {
                            getBean(beanName);
                        }
                    }
                }
                else {
                    getBean(beanName);
                }
            }
        }
        //...忽略部分代碼
    }

經(jīng)過一連串的輾轉(zhuǎn),最終調(diào)用到AbstractAutowireCapableBeanFactory#populateBean

附上調(diào)用鏈路

image.png

在populateBean中,會將所有的BeanPostProcessor應(yīng)用在這個bean上,包括AutowiredProcessor

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        //...忽略部分代碼
        PropertyDescriptor[] filteredPds = null;
        if (hasInstAwareBpps) {
            if (pvs == null) {
                pvs = mbd.getPropertyValues();
            }
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
          //###### 調(diào)用到postProcessProperties #####
                    PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        if (filteredPds == null) {
                            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                        }
                        pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvsToUse == null) {
                            return;
                        }
                    }
                    pvs = pvsToUse;
                }
            }
        }
    //...忽略部分代碼
    }

AutowiredProcessor的postProcessProperties()會進行注入操作,這需要找到注入的元數(shù)據(jù)(InjectionMetadata)

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {     
        //### 找到AutowringMetadata #####
        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()又調(diào)用到buildAutowiringMetadata(),生成代表可注入元素的InjectMetadata

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
        List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
        Class<?> targetClass = clazz;
        do {
            final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
            ReflectionUtils.doWithLocalFields(targetClass, field -> {
        //###### 找到帶有可注入注解的字段
                AnnotationAttributes 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;
                    }
                    boolean required = determineRequiredStatus(ann);
                    currElements.add(new AutowiredFieldElement(field, required));
                }
            });
            //...忽略部分代碼
    }

findAutowiredAnnotation()根據(jù)AutowiredProcessor的實例字段autowiredAnnotationTypes,去查看是否匹配,這個字段是在AutowiredProcessor創(chuàng)建時初始化,可以看到支持@Autowired,@Value,@Inject三種類型的注入標(biāo)識.最終據(jù)此完成注入

public AutowiredAnnotationBeanPostProcessor() {
        this.autowiredAnnotationTypes.add(Autowired.class);
        this.autowiredAnnotationTypes.add(Value.class);
        try {
            this.autowiredAnnotationTypes.add((Class&lt;? extends Annotation&gt;)
                    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.
        }
    }

后記

最后再來梳理一下整個流程.

首先是AutowiredPorcessor的BeanDefinition的注冊

=> 創(chuàng)建ApplicationContext

? => 創(chuàng)建AnnotatedBeanDefinitionReader

? => 注冊BeanDefinition registerAnnotationConfigProcessors

然后是AutowiredProcessor注冊為bean

=> registerBeanPostProcessors

最后是注入

? => 獲取bean getBean()

? => 創(chuàng)建bean doCreateBean()

? =>生成bean populateBean()

? => 應(yīng)用AutowiredProcessor ibp.postProcessProperties()

? => 找到可注入的字段 buildAutowiringMetadata

? => 注入 metadata.inject

至此,@Autowired生效邏輯梳理完成

到此這篇關(guān)于SpringBoot中@Autowired生效方式詳解的文章就介紹到這了,更多相關(guān)SpringBoot @Autowired內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 運用示例詳細總結(jié)Java多線程

    運用示例詳細總結(jié)Java多線程

    本文主要講解了Java多線程,該篇幅大量使用代碼以及圖片文字進行解析,可以讓小伙伴們了解該方面的知識更加迅速快捷
    2021-08-08
  • 快速定位Java 內(nèi)存OOM的問題

    快速定位Java 內(nèi)存OOM的問題

    這篇文章主要介紹了快速定位Java 內(nèi)存OOM的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • Java基礎(chǔ)之堆內(nèi)存溢出的解決

    Java基礎(chǔ)之堆內(nèi)存溢出的解決

    這篇文章主要介紹了Java基礎(chǔ)之堆內(nèi)存溢出的解決,文中有非常詳細的圖文示例及代碼示例,對正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下
    2021-05-05
  • 一次Jvm old過高的排查過程實戰(zhàn)記錄

    一次Jvm old過高的排查過程實戰(zhàn)記錄

    這篇文章主要給大家介紹了一次Jvm old過高的排查過程,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • 解決mybatis使用char類型字段查詢oracle數(shù)據(jù)庫時結(jié)果返回null問題

    解決mybatis使用char類型字段查詢oracle數(shù)據(jù)庫時結(jié)果返回null問題

    這篇文章主要介紹了mybatis使用char類型字段查詢oracle數(shù)據(jù)庫時結(jié)果返回null問題的解決方法,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-06-06
  • 微信企業(yè)號 根據(jù)錯誤碼返回錯誤信息類封裝

    微信企業(yè)號 根據(jù)錯誤碼返回錯誤信息類封裝

    這篇文章主要介紹了微信企業(yè)號 根據(jù)錯誤碼返回錯誤信息類封裝的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • Java Scanner 類的使用小結(jié)

    Java Scanner 類的使用小結(jié)

    在筆試編程過程中,關(guān)于數(shù)據(jù)的讀取如果迷迷糊糊,那后來的編程即使想法很對,實現(xiàn)很好,也是徒勞,于是在這里認(rèn)真總結(jié)了Java Scanner 類的使用,需要的朋友可以參考下
    2018-10-10
  • 詳解springboot如何更新json串里面的內(nèi)容

    詳解springboot如何更新json串里面的內(nèi)容

    這篇文章主要為大家介紹了springboot 如何更新json串里面的內(nèi)容,文中有詳細的解決方案供大家參考,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2023-10-10
  • 詳解Spring Boot中PATCH上傳文件的問題

    詳解Spring Boot中PATCH上傳文件的問題

    這篇文章主要介紹了詳解Spring Boot中PATCH上傳文件的問題,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • SpringBoot和Vue.js實現(xiàn)的前后端分離的用戶權(quán)限管理系統(tǒng)

    SpringBoot和Vue.js實現(xiàn)的前后端分離的用戶權(quán)限管理系統(tǒng)

    本文主要介紹了SpringBoot和Vue.js實現(xiàn)的前后端分離的用戶權(quán)限管理系統(tǒng),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04

最新評論

景泰县| 布拖县| 祁东县| 宁陕县| 小金县| 措勤县| 北碚区| 广昌县| 土默特左旗| 海原县| 广汉市| 小金县| 崇州市| 望城县| 土默特右旗| 天峻县| 湘潭市| 怀安县| 梓潼县| 肇源县| 邻水| 洞头县| 都兰县| 西华县| 广灵县| 台东市| 遵义县| 梅河口市| 克什克腾旗| 西丰县| 乐都县| 蕉岭县| 娱乐| 安达市| 博白县| 磐石市| 竹溪县| 民和| 茶陵县| 施甸县| 乌兰浩特市|