AnnotationConfigApplicationContext 源码分析(一):新建对象
本文是作者的个人学习笔记,仅做参考,Spring代码版本5.2.2
AnnotationConfigApplicationContext 作为继承GenericApplicationContext的子类,归属于Spring容器。同时该类实现了AnnotationConfigRegistry注解,在GenericApplicationContext的基础上为容器添加了一下两个功能:
对携带spring注解的类的注册。
扫描某个包下携带spring注解的类。
一、AnnotationConfigApplicationContext的基本使用
public class DemoApplication {
public static void main(String[] args) {
//1.新建AnnotationConfigApplicationContext对象
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
//2.注册配置类
applicationContext.register(MyConfiguration.class);
//3.启动容器
applicationContext.refresh();
//4.停止容器
applicationContext.stop();
//5.重启容器
applicationContext.start();
//6.关闭容器
applicationContext.close();
}
}
在AnnotationConfigApplicationContext最基础的使用中,我们启动一个容器需要三个步骤,对应上面的代码
- 新建AnnotationConfigApplicationContext对象
- 注册配置类
- 启动容器
剩下的三个步骤一般不会使用,有时间也将会阅读做分析
- 停止容器
- 重启容器
- 关闭容器
二、新建AnnotationConfigApplicationContext对象
/**
*
**/
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
/**
* Create a new AnnotationConfigApplicationContext that needs to be populated
* through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
* 创建一个新的AnnotationConfigApplicationContext,它需要通过{@link#register}调用填充,
* 然后手动{@linkplain#刷新}。
*
* 这里初始化了
*/
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
// Spring的扫描机制
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
// 内置一个DefaultListableBeanFactory对象
super(beanFactory);
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
}
由上面我们可以看到新建一个AnnotationConfigApplicationContext对象的时候,将实例化两个类,同时选择性的内置一个DefaultListableBeanFactory对象,以下将做具体的解析
1、 DefaultListableBeanFactory
这个类同GenericApplicationContext一样,都实现了BeanFactory接口,作为容器使用,但是两者没有继承关系。
GenericApplicationContext一般作为资源管理器使用,内部对于bean的管理往往是通过内置一个DefaultListableBeanFactory对象作为Bean管理器。
2、AnnotatedBeanDefinitionReader
/**
* Convenient adapter for programmatic registration of bean classes.
* <p>This is an alternative to {@link ClassPathBeanDefinitionScanner}, applying
* the same resolution of annotations but for explicitly registered classes only.
* 便于bean类的编程注册的适配器。
* <p>这是{@link ClassPathBeanDefinitionScanner}的另一种选择,它应用相同的注释解析,但仅适用于显式注册的类。
*/
public class AnnotatedBeanDefinitionReader {}
AnnotatedBeanDefinitionReader作为一个工具类,用于更方便的注册bean,接下来我们看一下这个类的构造函数
public class AnnotatedBeanDefinitionReader {
private final BeanDefinitionRegistry registry;
private ConditionEvaluator conditionEvaluator;
/**
* Create a new {@code AnnotatedBeanDefinitionReader} for the given registry,
* 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.
*
* 使用给定的{@link Environment},为给定的注册表创建一个新的{@code AnnotatedBeanDefinitionReader}。
* @param registry 以{@code BeanDefinitionRegistry}的形式将bean定义加载到{@code BeanFactory}
* @param environment 在计算bean定义概要文件时要使用的{@code Environment}。
* @since 3.1
*/
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
}
由上面代码可以看到,AnnotatedBeanDefinitionReader实例化需要的两个参数:
- BeanDefinitionRegistry:bean定义的注册器,由GenericApplicationContext实现,AnnotationConfigApplicationContext继承。
- Environment:环境变量,这里先不讨论,后面补充
AnnotatedBeanDefinitionReader实例化的逻辑:
- 持有一个BeanDefinitionRegistry/bean定义的注册器
- 通过registry,environment参数创建一个ConditionEvaluator对象,ConditionEvaluator对象的作用是用于解析注解@Conditional,这里先不做过多关注
- 通过工具类AnnotationConfigUtils,注册AnnotationConfigProcessors
接下来我们一次看一下ConditionEvaluator对象的创建和解析AnnotationConfigProcessors的注册
ConditionEvaluator对象的创建
/**
* Internal class used to evaluate {@link Conditional} annotations.
* 用于计算{@link Conditional}批注的内部类。
*
*/
class ConditionEvaluator {
private final ConditionContextImpl context;
/**
* Create a new {@link ConditionEvaluator} instance.
* 用于计算{@link Conditional}批注的内部类。
*/
public ConditionEvaluator(@Nullable BeanDefinitionRegistry registry,
@Nullable Environment environment, @Nullable ResourceLoader resourceLoader) {
this.context = new ConditionContextImpl(registry, environment, resourceLoader);
}
}
注册AnnotationConfigProcessors
public abstract class AnnotationConfigUtils {
/**
* Register all relevant annotation post processors in the given registry.
* @param registry the registry to operate on
* @param source the configuration source element (already extracted)
* that this registration was triggered from. May be {@code null}.
* @return a Set of BeanDefinitionHolders, containing all bean definitions
* that have actually been registered by this call
*
* 注册在给定的注册表中所有相关的批注后置处理器。
* @param source 触发此注册的配置源元素(已提取)。可能是{@code null}。
* @return 一组BeanDefinitionHolders,包含此调用实际注册的所有bean定义
*/
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
//步骤一
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
//步骤二
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
。。。
return beanDefs;
}
}
上面代码将分成几部分步骤:
- 获取DefaultListableBeanFactory对象,
- 需要注意的是,;
- 如果beanFactory(DefaultListableBeanFactory不为空),将为该对象设置两个对象,这里不做讨论:
- AnnotationAwareOrderComparator
- ContextAnnotationAutowireCandidateResolver
- 为当前容器registry注册多个BeanFactory后置处理器
- 注册的过程
- 利用后置处理器类对象和source对象(配置)生成一个BeanDefinition(Bean定义)对象;
- 用指定的bean名称和BeanDefinition对象,一起注册到registry中,并返回一个BeanDefinitionHolder对象(该对象持有BeanDefinition对象,bean的名称,bean的别名列表)
- 将BeanDefinitionHolder添加到指定列表中,作为最后的结果返回,这里并无利用到结果。
- BeanFactory后置处理器将干预Spring在注册,扫描,解析,生成BeanDefinition等的整个过程,后面将会具体解析。
- Spring支持用户注册自定义的BeanFactory后置处理器,同时,Spring在不同的容器中也注册实现不同功能的后置处理器,以下是在当前方法中注册的跟注解相关的后置处理器的简单介绍,在后面调用中将做具体解析
- CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME:
- 作用:内部托管配置注释处理器。
- 对应的类:ConfigurationClassPostProcessor.class
- AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME
- 作用:内部管理的自动注入注解处理器
- 对应的类:AutowiredAnnotationBeanPostProcessor.class
- COMMON_ANNOTATION_PROCESSOR_BEAN_NAME
- 作用:内部管理的JSR-250注释处理器
- 对应的类:CommonAnnotationBeanPostProcessor.class
- PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME
- 作用:内部管理的JPA注释处理器(不一定注入)。
- 对应的类:PersistenceAnnotationBeanPostProcessor.class
- EVENT_LISTENER_PROCESSOR_BEAN_NAME
- 作用:内部管理的@EventListener注释处理器
- 对应的类:EventListenerMethodProcessor.class
- EVENT_LISTENER_FACTORY_BEAN_NAME
- 作用:内部管理的EventListenerFactory。
- 对应的类:DefaultEventListenerFactory.class
- CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME:
- 注册的过程
3、ClassPathBeanDefinitionScanner
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
/**
* Create a new {@code ClassPathBeanDefinitionScanner} for the given bean factory and
* using the given {@link Environment} when evaluating bean definition profile metadata.
* @param registry the {@code BeanFactory} to load bean definitions into, in the form
* of a {@code BeanDefinitionRegistry}
* @param useDefaultFilters whether to include the default filters for the
* {@link org.springframework.stereotype.Component @Component},
* {@link org.springframework.stereotype.Repository @Repository},
* {@link org.springframework.stereotype.Service @Service}, and
* {@link org.springframework.stereotype.Controller @Controller} stereotype annotations
* @param environment the Spring {@link Environment} to use when evaluating bean
* definition profile metadata
* @param resourceLoader the {@link ResourceLoader} to use
*
* 为给定的bean工厂创建一个新的{@code ClassPathBeanDefinitionScanner},
* 并在计算bean定义概要文件元数据时使用给定的{@link Environment}。
* @param registry 以{@code BeanDefinitionRegistry}的形式将bean定义加载到{@code BeanFactory}
* @param useDefaultFilters 是否包含
* {@link org.springframework.stereotype.Component@Component}、
* {@link org.springframework.stereotype.Repository@Repository}、
* {@link org.springframework.stereotype.Service@Service}和
* {@link org.springframework.stereotype.Controller@Controller}构造型批注的默认筛选器
* @param environment 在计算bean定义概要文件元数据时使用的Spring{@link Environment}
* @param resourceLoader 要使用的{@link ResourceLoader}
*
* @since 4.3.6
*/
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
//关键代码,Spring 内部默认为true
//使用默认的Filters
if (useDefaultFilters) {
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(resourceLoader);
}
}
ClassPathBeanDefinitionScanner故名思义,是专门用于扫描类并将符合条件的类注册为BeanDefinition的工具对象。
ClassPathBeanDefinitionScanner构造函数的三个参数:
- registry(BeanDefinitionRegistry):
- useDefaultFilters(boolean):用于判断是否使用默认的注解过滤器(AnnotationTypeFilter)
- 注解过滤器/AnnotationTypeFilter:用于处理特定注解,有黑名单和白名单,先执行黑名单
- 黑名单/excludeFilters:标记该注解的类将不会被解析成Bean,即使在白名单中存在
- 白名单/includeFilters:标记该注解的类将会被解析成Bean
- 注解过滤器/AnnotationTypeFilter:用于处理特定注解,有黑名单和白名单,先执行黑名单
- environment(Environment):
- resourceLoader(ResourceLoader):资源加载器,这里先不做描述
- 这里资源加载器指的是AnnotationConfigApplicationContext对象
- 继承实现链为
- AnnotationConfigApplicationContext—>
- DefaultResourceLoader—>
- GenericApplicationContext—>
- AbstractApplicationContext—>
- DefaultResourceLoader—>
- ResourceLoader
构造函数初始化的过程:
1. 持有一个BeanDefinitionRegistry/bean对象(定义的注册器)
2. 判断是否使用默认的注解过滤器AnnotationTypeFilter.class,默认为是,如果是将注册以下注解
1. 白名单:@Component,@ManagedBean,@Named
2. 黑名单:无
3. 持有Environment对象
4. 通过resourceLoader对象生成对应的对象被ClassPathBeanDefinitionScanner持有,暂时不解析以下类
1. resourcePatternResolver(ResourcePatternResolver):新建PathMatchingResourcePatternResolver对象
2. metadataReaderFactory(MetadataReaderFactory):新建CachingMetadataReaderFactory对象
3. componentsIndex(CandidateComponentsIndex):利用resourceLoader的类加载器新建CandidateComponentsIndex对象
总结
在实例化AnnotationConfigApplicationContext对象的时候,做了三件事情:
- 新建一个AnnotatedBeanDefinitionReader对象用于注册一个类到容器中,而一般我们注册的类通常是配置类;
- 同时注册几个BeanFactory后置处理器到容器中;
- 新建一个ClassPathBeanDefinitionScanner对象用于扫描和注册类中。