91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring注解之@Import注解怎么使用

發布時間:2023-04-19 16:58:25 來源:億速云 閱讀:125 作者:iii 欄目:開發技術

本篇內容介紹了“Spring注解之@Import注解怎么使用”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

    介紹

    在Spring中@Import使用得比較頻繁,它得作用是導入bean,具體的導入方式有多種,特別在SpringBoot項目中,很多地方都使用到了@Import注解,特別對于一些和SpringBoot整合的組件,其實現都大量使用了@Import,例如使用Feign集成SpringBoot時會加上注解@EnableFeignClients,使用Dubbo時會使用@EnableDubbo等,這些注解里面都使用了@Import注解來注冊一些bean。

    @Import導入bean的三種方式

    @Import導入bean有三種方式,分別是導入普通類,實現ImportSelector接口的類,實現ImportBeanDefinitionRegistrar接口的類。

    普通類

    在開放過程中,盡量保持類不要太過于龐大,類過于龐大的話會變得臃腫復雜,不好維護,一個配置類中需要配置很多bean,且邏輯實現也比較復雜,代碼量大,如果全部都放在同一個配置類中,這顯然不太理智,這時候我們可以將每個bean單獨拿出來放到一個類里面,然后使用@Import注解導入,如下代碼所示。

    • 定義一個bean

    @Data
    public class UserBean {
        private String username;
        private String sex;
    }
    • 導入bean

    @Configuration
    @Import(value = {UserBean.class})  //注入普通Bean
    public class ImportConfiguration {
    
    }

    從上面可以看出只需要在配置類上面使用@Import注解導入對應Java Bean,然后這個bean就能注冊進IOC容器中。

    ImportSelector接口

    ImportSelector是一個接口,可以通過實現它來完成bean的注冊,它只有一個selectImports()方法,它會返回一個bean的名稱數組,這個數組中的bean名稱就會被注冊進IOC容器中。

    public class MyImportSelector implements ImportSelector {
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            return new String[]{UserBean.class.getName()};
        }
    }

    ImportBeanDefinitionRegistrar接口

    使用ImportBeanDefinitionRegistrar也可以注冊bean,它會傳入BeanDefinitionRegistry接口,然后進可以注冊bean,這里注冊的是bean的元信息BeanDefinition。

    public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            String name = UserBean.class.getName();
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(UserBean.class);
            builder.addPropertyValue("sex","男");
            AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
            registry.registerBeanDefinition(name, beanDefinition);
        }
    }

    源碼解析

    spring容器啟動后,會在ConfigurationClassParser解析類中解析@Import注解,解析出需要注冊的bean,下面就是最關鍵的代碼,通過調用processImports方法,然后解析出對應的bean,可以看出有幾個判斷,分別判斷是否是ImportSelector類型,ImportBeanDefinitionRegistrar類型,如果都不是,則證明是直接導入普通java類,如果是普通java類和ImportSelector類型,那么就會將要注冊的bean加入一個Map集合configurationClasses中,后續會將它進行注冊,如果是ImportBeanDefinitionRegistrar類型,那么會將其加入一個Map集合importBeanDefinitionRegistrars中,后續在擴展點會對它進行再次處理。

    private void processImports(ConfigurationClass configClass, ConfigurationClassParser.SourceClass currentSourceClass,
                                    Collection<ConfigurationClassParser.SourceClass> importCandidates, Predicate<String> exclusionFilter,
                                    boolean checkForCircularImports) {
            if (candidate.isAssignable(ImportSelector.class)) {
                Class<?> candidateClass = candidate.loadClass();
                ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
                        this.environment, this.resourceLoader, this.registry);
                Predicate<String> selectorFilter = selector.getExclusionFilter();
                if (selectorFilter != null) {
                    exclusionFilter = exclusionFilter.or(selectorFilter);
                }
                if (selector instanceof DeferredImportSelector deferredImportSelector) {
                    this.deferredImportSelectorHandler.handle(configClass, deferredImportSelector);
                } else {
                    String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                    Collection<ConfigurationClassParser.SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
                    processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
                }
            } else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                Class<?> candidateClass = candidate.loadClass();
                ImportBeanDefinitionRegistrar registrar =
                        ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
                                this.environment, this.resourceLoader, this.registry);
                configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
            } else {
                this.importStack.registerImport(
                        currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
            }
        }

    經過上面解析后,Spring會注冊Bean的元信息,會通過configClass.isImported()判斷bean是否是通過@Import方式導入的普通bean或者ImportSelector類型的導入的bean,如果是,則執行registerBeanDefinitionForImportedConfigurationClass,里面主要就是組裝成BeanDefinition,然后注冊進BeanFactory。

    private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, ConfigurationClassBeanDefinitionReader.TrackedConditionEvaluator trackedConditionEvaluator) {
            if (trackedConditionEvaluator.shouldSkip(configClass)) {
                String beanName = configClass.getBeanName();
                if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
                    this.registry.removeBeanDefinition(beanName);
                }
                this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
                return;
            }
            if (configClass.isImported()) {
                registerBeanDefinitionForImportedConfigurationClass(configClass);
            }
            for (BeanMethod beanMethod : configClass.getBeanMethods()) {
                loadBeanDefinitionsForBeanMethod(beanMethod);
            }
            loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
            loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
        }

    如果是通過ImportBeanDefinitionRegistrar方式,則會調用loadBeanDefinitionsFromRegistrars,里面會循環去執行我們自定義的ImportBeanDefinitionRegistrar,然后進行bean的元信息注冊。

    private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
        registrars.forEach((registrar, metadata) ->
            registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
     }

    從上面的源碼解析中,我們看出通過@Import直接導入普通的java類和導入實現了ImportSelector接口的類是直接注冊進BeanFactory,這兩者本質是一樣的,而通過實現ImportBeanDefinitionRegistrar接口方式的類則需要去實現我們自定義的注冊bean元信息的邏輯。

    “Spring注解之@Import注解怎么使用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    大同市| 谢通门县| 揭阳市| 昌吉市| 宜城市| 东乡族自治县| 太原市| 井冈山市| 河南省| 电白县| 湾仔区| 高台县| 普陀区| 石柱| 浙江省| 竹北市| 彭泽县| 仁怀市| 从化市| 巴彦淖尔市| 兴安县| 大理市| 关岭| 托里县| 观塘区| 社会| 南木林县| 曲麻莱县| 高清| 拉孜县| 梓潼县| 北海市| 枞阳县| 公主岭市| 油尖旺区| 余庆县| 大庆市| 渭南市| 蒙阴县| 台北市| 安义县|