1.AnnotationConfigApplicationContext詳細(xì)分析
1.1 概述
使用AnnotationConfigApplicationContext可以實(shí)現(xiàn)基于Java的配置類(lèi)(包括各種注解)加載Spring的應(yīng)用上下文。避免使用application.xml進(jìn)行配置音同。相比XML配置锡溯,更加便捷蹋订。
* Standalone application context, accepting annotated classes as input - in particular
* {@link Configuration @Configuration}-annotated classes, but also plain
* {@link org.springframework.stereotype.Component @Component} types and JSR-330 compliant
* classes using {@code javax.inject} annotations. Allows for registering classes one by
* one using {@link #register(Class...)} as well as for classpath scanning using
* {@link #scan(String...)}.
*
* <p>In case of multiple {@code @Configuration} classes, @{@link Bean} methods defined in
* later classes will override those defined in earlier classes. This can be leveraged to
* deliberately override certain bean definitions via an extra {@code @Configuration}
* class.
1.2 類(lèi)結(jié)構(gòu)層次分析
主要類(lèi)或接口說(shuō)明:
GenericApplicationContext——通用應(yīng)用上下文甲葬,內(nèi)部持有一個(gè)DefaultListableBeanFactory實(shí)例撇寞,這個(gè)類(lèi)實(shí)現(xiàn)了BeanDefinitionRegistry接口绍撞,可以在它身上使用任意的bean definition讀取器礁芦。典型的使用案例是:通過(guò)BeanFactoryRegistry接口注冊(cè)bean definitions蜻韭,然后調(diào)用refresh()方法來(lái)初始化那些帶有應(yīng)用上下文語(yǔ)義(org.springframework.context.ApplicationContextAware)的bean,自動(dòng)探測(cè)org.springframework.beans.factory.config.BeanFactoryPostProcessor等柿扣。
BeanDefinitionRegistry——用于持有像RootBeanDefinition和 ChildBeanDefinition實(shí)例的bean definitions的注冊(cè)表接口肖方。DefaultListableBeanFactory實(shí)現(xiàn)了這個(gè)接口,因此可以通過(guò)相應(yīng)的方法向beanFactory里面注冊(cè)bean未状。GenericApplicationContext內(nèi)置一個(gè)DefaultListableBeanFactory實(shí)例俯画,它對(duì)這個(gè)接口的實(shí)現(xiàn)實(shí)際上是通過(guò)調(diào)用這個(gè)實(shí)例的相應(yīng)方法實(shí)現(xiàn)的。
AbstractApplicationContext——ApplicationContext接口的抽象實(shí)現(xiàn)司草,沒(méi)有強(qiáng)制規(guī)定配置的存儲(chǔ)類(lèi)型艰垂,僅僅實(shí)現(xiàn)了通用的上下文功能。這個(gè)實(shí)現(xiàn)用到了模板方法設(shè)計(jì)模式埋虹,需要具體的子類(lèi)來(lái)實(shí)現(xiàn)其抽象方法猜憎。自動(dòng)通過(guò)registerBeanPostProcessors()方法注冊(cè)BeanFactoryPostProcessor, BeanPostProcessor和ApplicationListener的實(shí)例用來(lái)探測(cè)bean factory里的特殊bean——對(duì)比1分析
AnnotationConfigRegistry——注解配置注冊(cè)表。用于注解配置應(yīng)用上下文的通用接口吨岭,擁有一個(gè)注冊(cè)配置類(lèi)和掃描配置類(lèi)的方法拉宗。
1.2 構(gòu)造函數(shù)
- AnnotatedBeanDefinitionReader——BeanDefinition解析器用來(lái)解析帶注解的bean
- ClassPathBeanDefinitionScanner——bean的掃描器 用來(lái)掃描類(lèi)
- 注冊(cè)解析傳入的配置類(lèi)(使用類(lèi)配置的方式進(jìn)行解析)
- 調(diào)用容器的refresh方法初始化容器
/**
* Create a new AnnotationConfigApplicationContext that needs to be populated
* through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
*/
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
/**
* Create a new AnnotationConfigApplicationContext with the given DefaultListableBeanFactory.
* @param beanFactory the DefaultListableBeanFactory instance to use for this context
*/
public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
super(beanFactory);
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
/**
* Create a new AnnotationConfigApplicationContext, deriving bean definitions
* from the given annotated classes and automatically refreshing the context.
* @param annotatedClasses one or more annotated classes,
* e.g. {@link Configuration @Configuration} classes
*/
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
/**
* Create a new AnnotationConfigApplicationContext, scanning for bean definitions
* in the given packages and automatically refreshing the context.
* @param basePackages the packages to check for annotated classes
*/
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages);
refresh();
}
1.3 AnnotatedBeanDefinitionReader的構(gòu)造器
- 注解的條件判斷器ConditionEvaluator
該方法在初始化的時(shí)調(diào)用峦树,當(dāng)配置的類(lèi)上有@Conditional注解并且返回false的時(shí)候辣辫,容器就不處理該類(lèi) - AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)
這個(gè)是關(guān)鍵,注冊(cè)AnnotationConfigProcessor
/**
* Create a new {@code AnnotatedBeanDefinitionReader} for the given registry.
* If the registry is {@link EnvironmentCapable}, e.g. is an {@code ApplicationContext},
* the {@link Environment} will be inherited, otherwise a new
* {@link StandardEnvironment} will be created and used.
* @param registry the {@code BeanFactory} to load bean definitions into,
* in the form of a {@code BeanDefinitionRegistry}
* @see #AnnotatedBeanDefinitionReader(BeanDefinitionRegistry, Environment)
* @see #setEnvironment(Environment)
*/
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
/**
* Create a new {@code AnnotatedBeanDefinitionReader} for the given registry and using
* the given {@link Environment}.
* @param registry the {@code BeanFactory} to load bean definitions into,
* in the form of a {@code BeanDefinitionRegistry}
* @param environment the {@code Environment} to use when evaluating bean definition
* profiles.
* @since 3.1
*/
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
2.注解分析的關(guān)鍵方法loadBeanDefinitionsForBeanMethod
該方法具體實(shí)現(xiàn)對(duì)包括如下注解的處理魁巩。
- autowire
- initMethod
- destroyMethod
Conditional配置類(lèi)Ch5MainConfig.java
@Configuration
public class Ch5MainConfig {
@Bean("person")
public Person person(){
System.out.println("給容器中添加person.......");
return new Person("person",20);
}
@Conditional(WinCondition.class)
@Bean("lison")
public Person lison(){
System.out.println("給容器中添加lison.......");
return new Person("Lison",58);
}
@Conditional(LinCondition.class)
@Bean("james")//bean在容器中的ID為james, IOC容器MAP, map.put("id",value)
public Person james(){
System.out.println("給容器中添加james.......");
return new Person("james",20);
}
}
2.1 Ch5MainConfig注冊(cè)
是在 register(annotatedClasses)階段急灭。
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
調(diào)用棧:
2.2 @Bean的分析
是在refresh的invokeBeanFactoryPostProcessors(beanFactory)階段,核心方法是loadBeanDefinitionsForBeanMethod谷遂,該方法處理了各種各樣的注解葬馋。
-
調(diào)用棧
2.3 @Conditional(LinCondition.class)分析
ConditionEvaluator:配置的類(lèi)上有@Conditional注解并且返回false的時(shí)候,容器就不處理該類(lèi)。
-
調(diào)用到LinCondition時(shí)實(shí)際的棧信息
3.@Autowired
重點(diǎn)關(guān)注AutowiredAnnotationBeanPostProcessor后置處理器畴嘶。
* @author Juergen Hoeller
* @author Mark Fisher
* @since 2.5
* @see AutowiredAnnotationBeanPostProcessor
* @see Qualifier
* @see Value
*/
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* Declares whether the annotated dependency is required.
* <p>Defaults to {@code true}.
*/
boolean required() default true;
}
3.1 當(dāng)AutowiredAnnotationBeanPostProcessor 作為接口MergedBeanDefinitionPostProcessor的實(shí)現(xiàn)時(shí)
- AutowiredAnnotationBeanPostProcessor后置處理器的方法調(diào)用棧postProcessMergedBeanDefinition
該方法是在AbstractAutowireCapableBeanFactory.java的doCreateBean中調(diào)用的蛋逾。該方法是創(chuàng)建bean實(shí)例的核心方法: - 1)創(chuàng)建Bean的實(shí)例:createBeanInstance(beanName, mbd, args)
在此后:applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
調(diào)用AutowiredAnnotationBeanPostProcessor的方法postProcessMergedBeanDefinition - 2)populateBean;給bean的各種屬性賦值
- 3)initializeBean:初始化bean窗悯;
此時(shí)已將TestDao注入:
3.2 當(dāng)作為InstantiationAwareBeanPostProcessor接口的實(shí)現(xiàn)時(shí)
InstantiationAwareBeanPostProcessor 方法区匣,該步驟主要是populate bean ;通過(guò) @Autowired 注解所引用的對(duì)象給 bean 的屬性賦值蒋院。