1、入口
启动AnnotationConfigApplicationContext的main方法如下代码所示。
package com.bobo.springdubbo.provider;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.io.IOException;
public class AnnotationProvider {
public static void main(String[] args) throws IOException {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ServiceProviderConfig.class);
System.in.read();
}
}
AnnotationConfigApplicationContext的构造器参数如下图所示。
这里我们用的是第二个构造器。点进去,如下代码所示。
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
// 调用空参构造方法
this();
// 注册
register(componentClasses);
// 上下文刷新
refresh();
}
为了整个源码分析的过程有层次感,我将上面三行代码分三个标题去叙述。
2、this()
this()空参构造方法如下所示。
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
点进AnnotatedBeanDefinitionReader的构造方法,如下代码所示。
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;
// 顾名思义,基于注解配置方式的spring容器需要condition评估者
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
// 这行代码在AnnotationConfigApplicationContext体系里很关键,作用为注册注解配置的处理器的beanDefinition
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
下面列出一个表格展示一下在这里注册的beanDefinition。
beanName
| beanClass
| 目的
|
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
| ConfigurationClassPostProcessor
| BeanFactoryPostProcessor,@Configuration注解处理器
|
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
| AutowiredAnnotationBeanPostProcessor
| BeanPostProcessor,@Autowired注解处理器
|
org.springframework.context.annotation.internalCommonAnnotationProcessor
| CommonAnnotationBeanPostProcessor
| BeanPostProcessor,支持JSR-250的注解,如@Resource
|
org.springframework.context.annotation.internalPersistenceAnnotationProcessor
| PersistenceAnnotationBeanPostProcessor
| |
org.springframework.context.event.internalEventListenerProcessor
| EventListenerMethodProcessor
| |
org.springframework.context.event.internalEventListenerFactory
| DefaultEventListenerFactory
| |
再回过头看ClassPathBeanDefinitionScanner的构造方法做了什么,现在跟踪到如下代码的位置。
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
if (useDefaultFilters) {
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(resourceLoader);
}
registerDefaultFilters()方法用于注册默认的过滤器,什么意思呢,点进去就会看到如下这行关键代码。
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
includeFilters的类型为List<TypeFilter>,其实就是添加一个注解类型的过滤器,该过滤器专门用于过滤出@Component注解的,以及@Controller、@Service、@Repository等注解,ClassPathBeanDefinitionScanner的作用就是将打了@Component注解的类注册为beanDefinition。
3、register(componentClasses)
调用AnnotatedBeanDefinitionReader对象的register方法,将componentClasses注册为beanDefinition。
4、refresh()
到这里就是走我们熟悉的AbstractApplicationContext的refresh方法了。关于Spring ClassPathXmlApplicationContext的源码分析可以看我的这篇文章:Spring IOC容器启动流程与Bean生命周期源码分析
到这里我们就清楚了,AnnotationConfigApplicationContext相较于ClassPathXmlApplicationContext在容器refresh之前就是多了一些beanDefinition的注册,并没有什么特别的地方,那么到底这些beanDefinition何时发挥作用呢,这里我们挑几个比较重要的接着往下分析。
5、ConfigurationClassPostProcessor
由于它是一个beanFactoryPostProcessor,因此我们直接看refresh()方法内部的invokeBeanFactoryPostProcessors()方法,即执行BeanFactoryPostProcessors。
invokeBeanFactoryPostProcessors的过程十分复杂,这里我们写好步骤:
- 判断beanFactory是否为BeanDefinitionRegistry的子类,如果是,则先执行BeanDefinitionRegistryPostProcessors(顾名思义为用于bean声明注册的BeanFactoryPostProcessor,这可以联想到@Configuration注解了),否则直接执行context实例属性的beanFactoryPostProcessors,由于工厂实现一般为DefaultListableBeanFactory,因此为true
- 先执行实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
- 其实执行实现Ordered接口的BeanDefinitionRegistryPostProcessor
- 最后执行其它的BeanDefinitionRegistryPostProcessor直到没有为止
- 然后,执行所有BeanDefinitionRegistryPostProcessors和BeanFactoryPostProcessor的postProcessBeanFactory方法(其实2、3、4执行的是BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,BeanDefinitionRegistryPostProcessors继承BeanFactoryPostProcessor)
- 先执行实现PriorityOrdered接口的BeanFactoryPostProcessor
- 其实执行实现Ordered接口的BeanFactoryPostProcessor
- 最后执行其它的BeanFactoryPostProcessor直到没有为止
这里我们关注的ConfigurationClassPostProcessor在第二步就执行了。
这里我们先跟综到ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法里面去,如下图所示。
可以看到,我们一开始传入的componentClass(ServiceProviderConfig),会在这里作为一个configCandidate,即ConfigurationClass候选者。ConfigurationClassUtils.checkConfigurationClassCandidate()方法是如何校验的呢?简单来说就是看有没有@Configuration注解。
下面正式进入循环解析环节。
// 用于解析@Configuration class
ConfigurationClassParser 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 {
// 十分复杂,包括处理@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean方法等,不过在这一步只做解析,不做具体的加载beanDefinition
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// 读取模型并基于其内容创建bean定义
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
// 这一步将前面的@Import、@ImportResource、@Bean方法等解析出来的结果注册为beanDefinition
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
// 这一步判断是否有遗漏未解析的候选bean
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
// 判断有没有被解析过,如果没有则进行while循环解析
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
这里我们用几行关键的注释一笔带过,本文不做详细分析,正是因为Spring功能特性太丰富,光是ConfigurationClassPostProcessor就非常复杂。
本文还有以下几点没有讲清楚:
- ConfigurationClassPostProcessor深度剖析
- AnnotationConfigApplicationContext的String… basePackages构造器
- ClassPathBeanDefinitionScanner何时发挥作用
将在后面的文章进行分析。