Spring IOC (一)
注册 **注解配置类、配置类 **的全过程
AnnotationConfigApplicationContext 类
定义:
这个就是用Java配置类初始化的IOC容器 【以注解形式】
调用 AnnotationConfigApplicationContext(Class<?>… annotatedClasses) 构造方法,启动容器
构造方法:
主要是通过构造方法来实例化 IOC容器 的,现在来看看构造方法
方法 | 作用 | 方法的类 |
---|---|---|
super(); | 初始化beanFactory 初始化 DefaultListableBeanFactory | 父类方法 |
this(); | 初始化读取器 AnnotatedBeanDefinitionReader 扫描器 ClassPathBeanDefinitionScanner | 本类 |
register(annotatedClasses); | 注册配置类 annotatedClasses | reader 调用 |
refresh(); | 刷新容器,重要方法 | 本类 |
源码:
//根据参数类型可以知道,其实可以传入多个annotatedClasses,但是这种情况出现的比较少
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
//调用无参构造函数,会先调用父类GenericApplicationContext的构造函数
//父类的构造函数里面就是初始化DefaultListableBeanFactory,并且赋值给beanFactory
//本类的构造函数里面,初始化了一个读取器:AnnotatedBeanDefinitionReader read,一个扫描器ClassPathBeanDefinitionScanner scanner
//scanner的用处不是很大,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的
this();
//把传入的类进行注册,这里有两个情况,
//1. 传入传统的配置类
//2. 传入bean(虽然一般没有人会这么做
//spring把传统的带上@Configuration的配置类称之为FULL配置类,不带@Configuration的称之为Lite配置类
//但是我们这里先把带上@Configuration的配置类称之为传统配置类,不带的称之为普通bean
register(annotatedClasses);
//刷新
refresh();
}
super()
定义:
父类GenericApplicationContext的无参构造方法,用于初始化beanFactory
this()
定义:
用于初始化 读取器 AnnotatedBeanDefinitionReader
和扫描器 ClassPathBeanDefinitionScanner
方法:
主要是通过两个构造方法来实例化 读取器和扫描器,现在来看看构造方法
方法 | 作用 | 方法的类 |
---|---|---|
AnnotatedBeanDefinitionReader(this) | 实例化reader,参数为this,即context 因为他实现了 BeanDefinitionRegistry接口 用于注册配置类 | reader类 |
ClassPathBeanDefinitionScanner(this) | 实例化scanner,参数为this,即context 因为他实现了 BeanDefinitionRegistry接口 用于手动扫描类 | scanner类 |
源码:
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
// 隐式调用super()
//注解bean定义读取器,主要作用是用来读取被注解了的bean
private final AnnotatedBeanDefinitionReader reader;
//扫描器,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的
private final ClassPathBeanDefinitionScanner scanner;
public AnnotationConfigApplicationContext() {
//初始化一个Bean读取器
this.reader = new AnnotatedBeanDefinitionReader(this);
//初始化一个扫描器,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
}
AnnotatedBeanDefinitionReader()
定义:
整个方法作用是:注册了配置类后置处理器,就是将实例化 配置类后置处理器 的原料放入了BeanDefinitionMap中,还没有真正的创建 配置类后置处理器 这个Bean
作用:
- 注册了配置类后置处理器 —— 生成对应的BeanDefinition,加入Map 和 List
源码:
// 一、调用构造方法,进行注册 **注解配置处理器**
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
// ...
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
// 二、AnnotationConfigUtils类 #registerAnnotationConfigProcessors
// 判断是否已经注册 **配置类后置处理器**,如果没有,就去new一个BeanDefinition
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
// 常量:CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"; => 他指向的就是 **配置类后置处理器**
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// 如果 BeanDefinitionMap 中没有加载过这个类 internalConfigurationAnnotationProcessor
// 创建一个 **配置类后置处理器** 的BeanDefinition
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
// **registerPostProcessor()方法将bean放进Map中**
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
}
// 三、AnnotationConfigUtils类 #registerPostProcessor
// 设置BeanDefinition的信息,调用registry去注册
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
// ...
// 调用BeanFactory 注册BeanDefinition
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
// 四、DefaultListableBeanFactory类 #registerBeanDefinition
// 将bean定义推入BeanDefinitionMap 和 List
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
//这里就是把beanName作为key,ScopedProxyMode作为value,推到map里面
this.beanDefinitionMap.put(beanName, beanDefinition);
//beanDefinitionNames就是一个List<String>,这里就是把beanName放到List中去
this.beanDefinitionNames.add(beanName);
}
总结:
-
实例化Reader(),仅仅是将配置类后置处理器
ConfigurationClassPostProcessor
,注册到BeanDefinitionMap中,没有将他实例化,然后放入单例池 -
只是把原料放进了map,没有拉进工厂生产
流程:
- 构造方法,注册所有 注解配置处理器
- 发现 配置类后置处理器(属于 注解配置处理器)未注册
- 转换为BeanDefinition
- 放入Map
注解配置处理器有哪些?
-
ConfigurationClassPostProcessor —— 处理@Configuration类
-
AutowiredAnnotationBeanPostProcessor —— 解析@Autowired、@Value注解
-
CommonAnnotationBeanPostProcessor —— 解析@Resource注解、@PostConstruct、@PreDestroy
- JSR250标准,推荐使用@Resource
-
PersistenceAnnotationBeanPostProcessor —— Bean持久化到数据库有关的
- JPA包支持
-
EventListenerMethodProcessor —— 时间监视器
-
DefaultEventListenerFactory —— 支持@EventListener注解
register(annotatedClasses)
定义:
整个方法的作用是:注册了一群配置类们,【因为是可变参数嘛】,就是将实例化 配置类的原料放入了BeanDefinitionMap中,还没有真正创建 配置类 这群Bean
// 一、调用register(annotatedClasses)注册传入的配置类
// 注意,刚刚是注册**配置类后置处理器**,现在是注册**配置类**
// **配置类后置处理器**,是用来解析**配置类**的,帮助配置类实例化的
public void register(Class<?>... componentClasses) {
// ...
this.reader.register(componentClasses);
}
// 二、AnnotatedBeanDefinitionReader类 #register
// 开始循环注册**配置类**
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}
// 三、AnnotatedBeanDefinitionReader类 #registerBean
public void registerBean(Class<?> beanClass) {
// 执行注册**配置类**
doRegisterBean(beanClass, null, null, null, null);
}
// 四、AnnotatedBeanDefinitionReader类 #doRegisterBean
// 拿到**配置类**的注解,按要求来注册**配置类**
private <T> void doRegisterBean(Class<T> annotatedClass ...) {
// AnnotatedGenericBeanDefinition类,里面有一个getMetadata方法,可以拿到类上的注解
// 转换的目的就是为了拿到注解@,开始解析配置类的注解
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
// @Condition注解起效,可以跳过类
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
// @Scope注解起效,默认单例
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
// 获得beanName
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 解析通用注解
// @Lazy:懒加载;@Primary:优先使用注解;@DependsOn:依赖于某个Bean;@Role:标识角色;@Description:Bean描述信息
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
// beanName和AnnotatedGenericBeanDefinition 进行绑定
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
//注册,最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册,
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
// 五、AnnotationConfigUtils类 #registerBeanDefinition
// 拿到**配置类的所有bean定义信息**,调用registry去注册,如果有别名,还支持别名继续注册
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
// 获取beanName
String beanName = definitionHolder.getBeanName();
// 让 beanFactory 注册bean咯~~~~
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 别名注册,是通过 alias 与 beanName 绑定进行注册
// 有一个Map<alias,beanName> 存放这些
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
// 六、DefaultListableBeanFactory类 #registerBeanDefinition
// 将bean定义推入BeanDefinitionMap 和 List
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
//这里就是把beanName作为key,ScopedProxyMode作为value,推到map里面
this.beanDefinitionMap.put(beanName, beanDefinition);
//beanDefinitionNames就是一个List<String>,这里就是把beanName放到List中去
this.beanDefinitionNames.add(beanName);
}
总结:
-
register(annotatedClasses),仅仅是将配置类
annotatedClasses
,注册到BeanDefinitionMap中,没有将他实例化,然后放入单例池 -
只是把原料放进了map,没有拉进工厂生产
流程:
- 传入Class
- 读取,封装为AnnotatedGenericBeanDefinition
- 转换为BeanDefinition
- 放入Map
小总结:
**this()和register(annotatedClasses)**做的事情差不多
- 他们都是将类注册为BeanDefinition,提供原材料给**refresh()**方法
- this()针对的对象是注解配置类;而register(annotatedClasses)针对的对象是传入的参数annotatedClasses => 配置类;
- 他们将类注册为 BeanDefinition 的基础都是reader对象,只有reader对象能将类注册为BeanDefinition
refresh()方法后面在分析