日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

【Spring注解系列05】@Import注入原理

發布時間:2025/3/20 javascript 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Spring注解系列05】@Import注入原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.@Import注解

  • 用于注入指定的類,導入組件id默認是組件的全類名。
  • 只能作用于類上。
  • 屬性:value = {xx.class,xx.class}? ? ? ? 說明:xx.class為要導入到容器中的組件

屬性value中class分為三類:

? ? ?1)普通類直接注入

? ? ?2)實現ImportSelector接口的類

? ? ?3)實現ImportBeanDefinitionRegistrar接口的類

說明:

  • ImportSelector:返回需要導入的組件的全類名數組
  • ImportBeanDefinitionRegistrar:手動注冊bean到容器中;

?

2.@Import注入原理

import類注入是通過org.springframework.context.annotation.ConfigurationClassPostProcessor后置處理器來注入的。

核心方法:postProcessBeanDefinitionRegistry

/*** Derive further bean definitions from the configuration classes in the registry.*/@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {int registryId = System.identityHashCode(registry);//判斷后置處理器在registriesPostProcessed和factoriesPostProcessed中有沒有被調用過if (this.registriesPostProcessed.contains(registryId)) {throw new IllegalStateException("postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);}if (this.factoriesPostProcessed.contains(registryId)) {throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against " + registry);}//調用前保存registryId,防止被重復調用this.registriesPostProcessed.add(registryId);//注入標有@configuration的對象processConfigBeanDefinitions(registry);}/** 構建和校驗標有@configuration注解的對象* Build and validate a configuration model based on the registry of* {@link Configuration} classes. */public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {//configCandidates 需要注入的所有標注@configuration的類List<BeanDefinitionHolder> configCandidates = new ArrayList<>();String[] candidateNames = registry.getBeanDefinitionNames();…………// Return immediately if no @Configuration classes were foundif (configCandidates.isEmpty()) {return;}…………// Parse each @Configuration classConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment,this.resourceLoader, this.componentScanBeanNameGenerator, registry);Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());do {//核心方法 解析@configuration的類parser.parse(candidates);parser.validate();…………}while (!candidates.isEmpty());// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes…………}// 進行 parse解析,獲得configClass protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {processConfigurationClass(new ConfigurationClass(metadata, beanName));}protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {…………//注入configuration class的上級類// Recursively process the configuration class and its superclass hierarchy.SourceClass sourceClass = asSourceClass(configClass);do {//核心方法,加載上級類,直到為nullsourceClass = doProcessConfigurationClass(configClass, sourceClass);}while (sourceClass != null);this.configurationClasses.put(configClass, configClass);}/*** Apply processing and build a complete {@link ConfigurationClass} by reading the* annotations, members and methods from the source class. This method can be called* multiple times as relevant sources are discovered.* @param configClass the configuration class being build* @param sourceClass a source class* @return the superclass, or {@code null} if none found or previously processed*/@Nullableprotected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)throws IOException {//加載@Component組件if (configClass.getMetadata().isAnnotated(Component.class.getName())) {// Recursively process any member (nested) classes firstprocessMemberClasses(configClass, sourceClass);}//加載@PropertySource組件// Process any @PropertySource annotationsfor (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class,org.springframework.context.annotation.PropertySource.class)) {…………}//加載@ComponentScan 組件// Process any @ComponentScan annotationsSet<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);if (!componentScans.isEmpty() &&!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {for (AnnotationAttributes componentScan : componentScans) {// The config class is annotated with @ComponentScan -> perform the scan immediately…………}}}//加載@Import 組件 這就是Import導入的組件// Process any @Import annotationsprocessImports(configClass, sourceClass, getImports(sourceClass), true);//@ImportResource 組件// Process any @ImportResource annotationsAnnotationAttributes importResource =AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);…………}//@Bean組件// Process individual @Bean methodsSet<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);for (MethodMetadata methodMetadata : beanMethods) {configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));}// Process default methods on interfacesprocessInterfaces(configClass, sourceClass);// Process superclass, if anyif (sourceClass.getMetadata().hasSuperClass()) {String superclass = sourceClass.getMetadata().getSuperClassName();if (superclass != null && !superclass.startsWith("java") &&!this.knownSuperclasses.containsKey(superclass)) {this.knownSuperclasses.put(superclass, configClass);// Superclass found, return its annotation metadata and recursereturn sourceClass.getSuperClass();}}// No superclass -> processing is completereturn null;}

?

3.實例

實體類:

public class ImportBean {}public class ImportBean2 {}public class ImportBean3 {}public class ImportBean4 {}

實現ImportSelector和ImportBeanDefinitionRegistrar接口類

//自定義邏輯返回需要導入的組件 public class BeanImportSelector implements ImportSelector {//返回值,就是到導入到容器中的組件全類名//AnnotationMetadata:當前標注@Import注解的類的所有注解信息@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {//importingClassMetadata//方法不要返回null值System.out.println(importingClassMetadata);return new String[]{"com.java.model.ImportBean2","com.java.model.ImportBean3"};} }public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {/*** AnnotationMetadata:當前類的注解信息* BeanDefinitionRegistry:BeanDefinition注冊類;* 把所有需要添加到容器中的bean;調用* BeanDefinitionRegistry.registerBeanDefinition手工注冊進來*/@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//指定Bean定義信息;(Bean的類型,Bean。。。)RootBeanDefinition beanDefinition = new RootBeanDefinition(ImportBean4.class);//注冊一個Bean,指定bean名registry.registerBeanDefinition("registrar_ImportBean4", beanDefinition);} }

配置類:

@Configuration @Import({ImportBean.class, BeanImportSelector.class, MyImportBeanDefinitionRegistrar.class}) public class BeanImportConfig {}

測試類:

public class BeanImportTest {public static void main(String[] args) {ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanImportConfig.class);String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();for (String name : beanDefinitionNames) {System.out.println(name);}} }運行結果: org.springframework.core.type.StandardAnnotationMetadata@1a0dcaa org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory beanImportConfig com.java.model.ImportBean //普通類直接注入 com.java.model.ImportBean2 //通過ImportSelector接口注入 com.java.model.ImportBean3 //通過ImportSelector接口注入 registrar_ImportBean4 //通過ImportBeanDefinitionRegistrar注入

?

?

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的【Spring注解系列05】@Import注入原理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。