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 配置的包路径。
这一步会将一些后置处理器注册到 BeanDefinition 中,也就是将几个后置处理器接口封装成一个个的 bean定义。这些后置处理器有实现 bean工厂的后置处理器,也有实现了bean的后置处理器。比如:ConfigurationClassPostProcessor 实现了 bean 工厂后置处理器,用于解析加了 @Configuration 注解、 @ComponmentScan 、@ComponmentScans、@Import 等这些注解。还有一些解析 @Autowired注解的、解析 @Resource、@Ejb注解的,还有一些是监听器的处理器。
这样做的目的是:在生产 bean 的时候要用到这些后置处理器。
加载过后的beanDefinition 中的样子
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(IOCConfig.class);
// 手动需要设置一个需要扫描的包
context.scan("com.ioc");
}