Spring上下文构造方法的初始化
JavaConfig 方式加载 Spring 容器
JavaConfig 方式加载 Spring 容器的是 new 一个 AnnotationConfigApplicationContext()
- 代码如下:
@Configuration
@ComponentScan
public class SpringConfig {
@Bean
public Bean2 getUserServie(){
return new Bean2();
}
}
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = applicationContext.getBean(UserService.class);
userService.doSomething1();
}
源码解读
在这个构造方法中,分为三步:
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
// 1:无参构造方法的初始化
this();
// 2:将配置类注册到 beanDefinition中去
this.register(componentClasses);
// 3:调用refresh() 开始IOC 流程
this.refresh();
}
无参构造方法初始化
分为两步:
- 调用父类的构造方法
- 本类的构造方法
调用父类的构造方法
在父类的构造方法中,初始化BeanFactory 接口的实现类:DefaultListAbleBeanFactory。这个类是用来使用工厂模式+反射生成bean的
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
调用本类的构造方法
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
-
new 一个 BeanDefinationReader,它是用来读取配置类的,并封装成一系列的BeanDefinition ,后续spring 基于这个bean定义去生产bean
-
new 一个 BeanDefinitionScanner,它是用来扫描在外部添加需要被扫描的类,并不会扫描配置文件中的通过componmentScan 配置的包路径。
创建 BeanDefinationReader
这一步会将一些后置处理器注册到 BeanDefinition 中,也就是将几个后置处理器接口封装成一个个的 bean定义。这些后置处理器有实现 bean工厂的后置处理器,也有实现了bean的后置处理器。比如:ConfigurationClassPostProcessor 实现了 bean 工厂后置处理器,用于解析加了 @Configuration 注解、 @ComponmentScan 、@ComponmentScans、@Import 等这些注解。还有一些解析 @Autowired注解的、解析 @Resource、@Ejb注解的,还有一些是监听器的处理器。
这样做的目的是:在生产 bean 的时候要用到这些后置处理器。
加载过后的beanDefinition 中的样子
创建 BeanDefinitionScanner
- scanner 是为了解析手动加了扫描路径的那些类,注册到 bean定义中, 它不会去扫描配置文件中写的@ComponmentScan 的路径,那些路径是 BeanDefinationReader 中的后置处理器去扫描的。
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(IOCConfig.class);
// 手动需要设置一个需要扫描的包
context.scan("com.ioc");
}
将配置类注册到 beanDefinition
- 这一步的目的是将 配置类存入 beanDefinition 中,因为并没有解析它
至此,配置文件的注册都完成了,主要就是将一些后置处理器、配置文件信息封装成 beanDefinition ,以及创建bean工厂。接下来就是 IOC 流程。