2.Spring5底层原理之BeanFactory的实现

spring / 2022-04-01

为了解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()方法中去看看。

image-20220331113954855

这里可以看到,这里添加了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注解

image-20220331101448077

到现在为止,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();

总结

  1. beanFactory不会主导调用beanFactory后处理器
  2. 不会主动添加bean后处理器
  3. 不会主动初始化单例