2.Spring5底层原理之BeanFactory的实现
为了解BeanFactory的实现原理,我们来自己写一个例子。
例子
创建一个类,名字叫做TestBeanFactory,该类的内容如下
public class TestBeanFactory {
public static void main(String[] args) {
}
@Configuration
static class Config{
@Bean
public Bean1 bean1(){
return new Bean1();
}
@Bean
public Bean2 bean2(){
return new Bean2();
}
}
static class Bean1{
private static final Logger log = LoggerFactory.getLogger(Bean1.class);
@Autowired
private Bean2 bean2;
public Bean1(){
log.debug("构造 Bean1()");
}
public Bean2 getBean2() {
return bean2;
}
}
static class Bean2{
private static final Logger log = LoggerFactory.getLogger(Bean2.class);
public Bean2(){
log.debug("构造 Bean2()");
}
}
}
在TestBeanFactory类中,我们还创建了Config内部类,并用@Configuration注解标注,我们还另外创建了两个类Bean1、Bean2,以及构造方法,在Config类中创建两个Bean的实例,我们知道在Spring中,用@Configuration标注的类是配置类,@Bean注解会让Spring帮我们创建类的实例。接下来,我们在TestBeanFactory的main方法中,添加如下代码
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// bean的定义 (class scope 初始化 销毁)
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class)
.setScope("singleton").getBeanDefinition();
beanFactory.registerBeanDefinition("config",beanDefinition);
// 注册后处理器,主要功能:补充了一些bean定义
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
System.out.println("-----------");
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
}
输出如下
config
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
-----------
config
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
bean1
bean2
添加的这些代码做了哪些事情呢?从上一节的内容我们知道,BeanFactory的默认实现是DefaultListableBeanFactory类,我们自己把DefaultListableBeanFactory的实例创建出来,来观察BeanFactory是如何帮我们创建Bean的。
生成Bean定义
首先要生成Bean的定义,AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
这句代码就是用来生成beanDefinition的。beanDefinition用来描述bean是单例还是多例,初始化和销毁、是否延迟初始等一些信息。
将Bean定义注册到BeanFactory
然后我们将beanDefinition注册到beanFactory中。
BeanFactory后处理器
其实在基础的beanFactory中,没有包含处理@Configuration,@Bean这些注解的能力,需要绑定注解配置的处理器,进行处理,增加一些处理这些的bean的定义AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
。
我们到registerAnnotationConfigProcessors()方法中去看看。
这里可以看到,这里添加了ConfigurationClassPostProcessor后处理器,用来处理@Configuration。
执行BeanFactory后处理器
但是我们注册了后处理器发现,依然没有bean1和bean2的beanDefinitionName。这是因为,注册了之后,还需要执行才可以。
注:上面输出内容中 “-----------”之前,没有bean1和bean2的beanDefinitionName
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
这一处的代码,就是获取到所有后处理器的bean进行执行,BeanFactoryPostProcessor是ConfigurationClassPostProcessor的父类,这里用ConfigurationClassPostProcessor.class也可以。
在执行中可以看到,@Configuration的parse会解析@Bean注解
到现在为止,Config,Bean1,Bean2的实例都还没有被创建,因为我们还没有使用到他们。接下来我们通过beanFactory获取一下Bean1的实例,并且通过bean1获取Bean2的实例。
// 忽略之前的代码
Bean1 bean1 = beanFactory.getBean(Bean1.class);
System.out.println(bean1.getBean2());
输出如下
17:21:45.391 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean1'
17:21:45.406 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'config'
17:21:45.472 [main] DEBUG com.zhaojun.springsource.TestBeanFactory$Bean1 - 构造 Bean1()
null
通过日志可以看到,Bean1的构造方法被调用,Config的实例也被创建,但是Bean2却没有被注入进来,但是我们明明使用了@Autowired注解呀。
其实在之前的输出日志中我们可以看到,注册后处理器之后,增加了好几个bean定义名
- org.springframework.context.annotation.internalConfigurationAnnotationProcessor
- org.springframework.context.annotation.internalAutowiredAnnotationProcessor
- org.springframework.context.annotation.internalCommonAnnotationProcessor
- org.springframework.context.event.internalEventListenerProcessor
- org.springframework.context.event.internalEventListenerFactory
我们执行了下面的代码,让beanFactory获取到了Config,Bean1,Bean2的bean定义
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
Bean后处理器
其实@Autowired 注解的处理也需要执行后处理器
org.springframework.context.annotation.internalAutowiredAnnotationProcessor 就是处理@Autowired的
org.springframework.context.annotation.internalCommonAnnotationProcessor 这是处理@Resource的
我们再增加下面的代码(在获取bean1之前),这行代码相当于将beanFactory与bean的后处理器建立关联
beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
重新运行,输出如下
17:40:10.358 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean1'
17:40:10.359 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'config'
17:40:10.384 [main] DEBUG com.zhaojun.springsource.TestBeanFactory$Bean1 - 构造 Bean1()
17:40:10.395 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean2'
17:40:10.395 [main] DEBUG com.zhaojun.springsource.TestBeanFactory$Bean2 - 构造 Bean2()
com.zhaojun.springsource.TestBeanFactory$Bean2@4b0d79fc
现在@Autowired起作用了。
前面我们看到beanfactory默认是使用到bean才会去创建实例的,我们可以使用这行代码,提前创建好所有单例对象。可以自己试试,在getBean之前看日志是否已经创建好了对象。
beanFactory.preInstantiateSingletons();
总结
- beanFactory不会主动调用beanFactory后处理器
- 不会主动添加bean后处理器
- 不会主动初始化单例