使用AnnotationConfigApplicationContext注冊配置類


1、 AnnotationConfigApplicationContext功能

該類可以實現基於Java的配置類加載自定義在Spring的應用上下文的bean。

1.1 使用方式一:在構造方法中完成注冊和刷新

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MessageConfiguration.class);
System.out.println(ctx.getBean("beanName"));)//根據bean的名字獲得與之對應的實例。

public AnnotationConfigApplicationContext(Class... annotatedClasses) {
this();
this.register(annotatedClasses);
this.refresh();
}

 

1.2 使用方式二:掃描包路徑下所有的配置類,最后刷新

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("org.spring.springboot");
ctx.refresh();
可以直接以包名作為參數傳入。
public AnnotationConfigApplicationContext(String... basePackages) {
this();
this.scan(basePackages);
this.refresh();
}

 

使用方式三:通過使用register方法具體到注冊哪個配置類,最后刷新。

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class);
ctx.refresh();

 

2、 分析AnnotationConfigApplicationContext

AnnotationConfigApplicationContext繼承了GenericApplicationContext並實現了接口AnnotationConfigRegistry 

 

 

 

 

2.1 接口:AnnotationConfigRegistry注冊方法和掃描方法。注解配置注冊表。用於注解配置應用上下文的通用接口,
擁有一個注冊配置類和掃描配置類的方法。


2.2 GenericApplicationContext通用應用上下文。
GenericApplicationContext 繼承 AbstractApplicationContext 實現 BeanDefinitionRegistry,內部持有一個
DefaultListableBeanFactory實例,這個類實現了BeanDefinitionRegistry接口,可以在它身上使用任意的bean definition讀取器。

 

 


2.2.1 AbstractApplicationContext
ApplicationContext接口的抽象實現,沒有強制規定配置的存儲類型,僅僅實現了通用的上下文功能。
這個實現用到了模板方法設計模式,需要具體的子類來實現其抽象方法。自動通過registerBeanPostProcessors()
方法注冊BeanFactoryPostProcessor, BeanPostProcessor和ApplicationListener的實例用來探測bean factory里的特殊bean。


2.2.2 BeanDefinitionRegistry
用於持有像RootBeanDefinition和 ChildBeanDefinition實例的bean definitions的注冊表接口。GenericApplicationContext
類中的實例DefaultListableBeanFactory實現了這個接口,它對這個接口的實現實際上是通過調用這個實例的相應方法實現的,
因此可以通過相應的方法向beanFactory里面注冊bean。

源碼:

public interface BeanDefinitionRegistry extends AliasRegistry {
void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;

void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

boolean containsBeanDefinition(String var1);

String[] getBeanDefinitionNames();

int getBeanDefinitionCount();

boolean isBeanNameInUse(String var1);
}

 

2.3 構造方法
AnnotatedBeanDefinitionReader——BeanDefinition解析器用來解析帶注解的bean


2.3.1 AnnotatedBeanDefinitionReader的構造器
注解的條件判斷器ConditionEvaluator
該方法在初始化的時調用,當配置的類上有@Conditional注解並且返回false的時候,容器就不處理該類
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)
這個是關鍵,注冊AnnotationConfigProcessor

// 默認使用三個bean處理器
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
    registerAnnotationConfigProcessors(registry, (Object)null);
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet(8);
        RootBeanDefinition def;
        if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalConfigurationAnnotationProcessor")) {
            def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"));
        }

        if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalAutowiredAnnotationProcessor")) {
            def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"));
        }

        if (jsr250Present && !registry.containsBeanDefinition("org.springframework.context.annotation.internalCommonAnnotationProcessor")) {
            def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalCommonAnnotationProcessor"));
        }

 

2.3.1.1 @Bean的分析
是在refresh的invokeBeanFactoryPostProcessors(beanFactory)階段,核心方法是loadBeanDefinitionsForBeanMethod,該方法處理了各種各樣的注解。
注解分析的關鍵方法loadBeanDefinitionsForBeanMethod
該方法具體實現對包括如下注解的處理。
autowire
initMethod
destroyMethod

是在refresh的invokeBeanFactoryPostProcessors(beanFactory)階段,核心方法是loadBeanDefinitionsForBeanMethod,
該方法處理了各種各樣的注解。
2.3.1.2 ConditionEvaluator:配置的類上有@Conditional注解並且返回false的時候,容器就不處理該類

2.3.1.3 @Autowired 重點關注AutowiredAnnotationBeanPostProcessor后置處理器。

2.3.1.4 當AutowiredAnnotationBeanPostProcessor 作為接口MergedBeanDefinitionPostProcessor的實現時
AutowiredAnnotationBeanPostProcessor后置處理器的方法調用棧postProcessMergedBeanDefinition
該方法是在AbstractAutowireCapableBeanFactory.java的doCreateBean中調用的。該方法是創建bean實例的核心方法:

  • 1)創建Bean的實例:createBeanInstance(beanName, mbd, args)
  • 在此后:applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
  • 調用AutowiredAnnotationBeanPostProcessor的方法postProcessMergedBeanDefinition
  • 2)populateBean;給bean的各種屬性賦值
  • 3)initializeBean:初始化bean;

 

2.3.2 ClassPathBeanDefinitionScanner——bean的掃描器 用來掃描類


注冊解析傳入的配置類(使用類配置的方式進行解析)
調用容器的refresh方法初始化容器


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM