本文内容
后面所有的笔记,都是基于Java配置形式来学习的,所以,默认情况下,都是以AnnotationConfigApplicationContext为例;本文主要记录,spring在真正开始初始化bean之前,需要完成的工作:大体主要包括三部分
- 初始化AnnotatedBeanDefinitionReader
- 初始化ClassPathBeanDefinitionScanner
- 将配置类注册到BeanDefinitionMap中
源码解析
前面文章有说过,通过 AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
的形式来启动spring,会进入到
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
//在this()中调用父类的方法 创建了 DefaultListableBeanFactory(这就是平常说的springbean工厂)
this();
//把annotatedClasses(AppConfig.java)放到spring容器中
register(annotatedClasses);
refresh();
}
这个构造方法中,refresh()这个方法是spring初始化实例化bean的;this()和register(annotatedClasses);分别是初始化spring默认自带的后置处理器和将配置类注入到BeanDefinitionMap中
this()
public AnnotationConfigApplicationContext() {
/**
* 创建一个读取注解的bean定义读取器
* bean定义其实就是beanDefinition
* 在这个方法里面 声明了六个比较重要的bean,并将这个几个bean存到了beanDefinitionMap里面
* CommonAnnotationBeanPostProcessor
* RequiredAnnotationBeanPostProcessor
* AutowiredAnnotationBeanPostProcessor
* ConfigurationClassPostProcessor
*
* 这里的reader主要完成了对配置类(@Configuration)的处理,将配置类添加到beanDefinitionMap中;
* 后面将普通bean扫描到beanDefinitionMap的时候,用的是另外new出来的scanner,并根据.class文件new出来一个ScannedGenericBeanDefinition对象
*/
this.reader = new AnnotatedBeanDefinitionReader(this);
/**
* 实际上完成包扫描并不是这里的scanner完成的。而是spring自己new的一个ClassPathBeanDefinitionScanner完成的
* 这里的scanner是为了程序员能够在外部调用annotationConfigApplicationbContext对象,简单而言,spring遵循了开闭原则
*
* 这个方法里面的registerDefaultFilters这个方法也比较重要(这个方法有两个集合变量:includeFilters和excludeFilters),
* 在后面将class扫描出来并放到beanDefinitionMap的时候,有用到这个地方
* registerDefaultFilters 这个方法,向一个list(includeFilters)中添加了三个值
* Component.class
* javax.annotation.ManagedBean
* javax.inject.Named
*
* 在扫描@ComponentScan下面的bean时,获取到的是包路径下所有的.class文件,那spring如何区分是要将哪些bean注入的呢?就和这里的includeFilters有关系。在后面包扫描会加注释
*/
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
关于this()方法,里面只有两行代码,我对着两行代码完成的工作,在注释中,做了详细的介绍;就不再叙述了
register(annotatedClasses);
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
/**
* 创建一个beanDefinition,beanDefinition保存了类的其他信息,比如:元注解信息、lazy属性等
*/
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
/**
* 判断是否需要跳过解析:应该是对@Conditional注解的判断
*/
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(instanceSupplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
//添加类的作用域
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
//beanDefinitionHolder也是一种数据结构 先暂时认为definitionHolder比beanDefinition存储的信息更为丰富
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
/**
* 这是是把创建的definitionHolder注册到registry
* registry就是AnnotationConfigApplicationContext初始化创建的DefaultListableBeanFactory
*
* 内部调用的是DefautListableBeanFactory.registerBeanDefinition()方法
*/
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
这里之所以将配置类,加入到BeanDefinitionMap中,我觉得是因为在后面扫描bean的时候,需要用到配置类中的@ComponentScan注解,所以,在之前,先将配置类添加到beanDefinitionMap中
这是这两个方法的解析和学习,后面的文章中,我们来看refresh完成的工作