提起BeanFactory一定不陌生,都知道它是容器的核心接口,负责生成和管理bean的一个工厂,但是它会负责具体实现吗?它可以识别@Bean、@Autowired这些注解吗?
其实BeanFactory不负责具体的实现,只不过是它的实现类帮助它扩展了一些功能,先来看一下关系图:
DefaultListableBeanFactory是bean工厂的一个默认实现,而AbstractBeanDefinition在它的基础上可以定义一些bean去注册到该工厂中,比如bean的初始化、scope等等。
以如下代码说明:
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
AbstractBeanDefinition beanDefinition =BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();beanFactory.registerBeanDefinition("config", beanDefinition);
String[] names = beanFactory.getBeanDefinitionNames();
System.out.println(Arrays.toString(names));
首先创建了带有@Configuration的类Config以及它里面有@Bean注解的Bean1、Bean2两个类,当我们使用BeanDefinitionBuilder.genericBeanDefinition()构建出bean并且将它加入到默认工厂中,此时如果打印工厂中已经定义的bean的名字是否会输出bean1、bean2呢?答案是不会的,因为这些东西是通过后处理器去实现的,而BeanFactory是不会主动调用后处理器的。
//添加常用的后处理器给BeanFactory
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
上面的代码只是给BeanFactory添加了处理器,但是处理器还未真正的开始工作。
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
上面的代码是添加BeanFactory后处理器,这时候后处理器才开始真正工作,该处理器的作用是补充了一些Bean的定义,此时再次打印会发现bean1、bean2已经输出。
对于@Autowired、@Resource注解需要使用的是Bean后处理器,该处理器针对bean的生命周期进行扩展,所以以下代码与上述同理。
beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream()
.forEach(beanPostProcessor -> { beanFactory.addBeanPostProcessor(beanPostProcessor);});
假若没有添加bean后处理器,beanFactory.getBean(Bean1.class).getBean2())获取到的bean2是为空的,因为没有办法去识别注解。
beanFactory会事先帮我们准备好所有的Bean吗?答案是不会的,因为只有调用的时候才会进行准备,但是我们可以告诉它事先准备。
beanFactory.preInstantiateSingletons();
假若@Autowired、@Resource同时存在,那么谁会先执行呢?
其实在调用registerAnnotationConfigProcessors();的时候,已经去设置了比较器。
而且这个比较器是饿汉式的设计模式。
有了比较器是通过什么方式比较的呢?是通过getOrder方法,这个方法一定不陌生,因为数字越小越线执行嘛
首先看一下Autowired和Common后处理器的代码:
综上所述BeanFactory不会主动调用 BeanFactory 后处理器和Bean后处理器,并且它不会主动初始化所有的单例,并且后处理器它其实是有排序滴。