BeanFactory
我们来用 BeanFactory 的子实现类 DefaultListableBeanFactory 基本的就可以对bean进行一些定义也就是将bean加入bean工厂;
下面代码是一个简单的Bean注册,但是Bean1中自动装配了Bean2:
@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);
public Bean1() {
log.debug("构造 Bean1()");
}
@Autowired
private Bean2 bean2;
public Bean2 getBean2() {
return bean2;
}
}
static class Bean2 {
private static final Logger log = LoggerFactory.getLogger(Bean2.class);
public Bean2() {
log.debug("构造 Bean2()");
}
}
这里就是一个简单的Bean定义(Config.class)并注册到了BeanFactory:
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// bean 的定义(class,scope,初始化)
AbstractBeanDefinition beanDefinition =
BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
beanFactory.registerBeanDefinition("config",beanDefinition);
打印一下结果看看:
发现我们确实把Config.class注册进去了,我们获得的是BeanName所以未我们设置的config,当然也可以设置其他。
这里发现注册进去的只有外部的一个类,内部的Bean1、Bean2并没有注入到BeanFacotry中。
也就是说@Configuration、@Bean没有识别到,或者说原本的BeanFactory的子实现类中缺少实现对这几个注解解析的能力,功能不是其提供的。
AnnotationConfigUtils
我们需要这个工具类用于注册一些后处理器,让功能完整。
// 给BeanFactory添加一些常用的后处理器(用于解析注解 但是现在还没有调用,只是注册了这些后处理器)
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
注册之后我们再次打印一下 beanFactory中注册了的Bean:
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
结果除了我们自己注册的config,多了几个:
这几个的用途就在于完善一些BeanFactory的一些注解的识别,自动装配的实现等功能,我们继续往下。
internalConfigurationAnnotationProcessor: 解析@Configuration注解 以及里面的@Bean等注解
internalAutowiredAnnotationProcessor:解析@Autowired自动装配注解
internalCommonAnnotationProcessor:解析@Resource注解
internalEventListenerProcessor:
internalEventListenerFactory:
// 给BeanFactory 添加一些常用的后处理器 我们根据类型(getBeansOfType)获取后处理器
// 类型为 BeanFactoryPostProcessor.class
// 使用 internalConfigurationAnnotationProcessor 后处理器 解析注解 将两个 Bean注入
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().stream().forEach(BeanFactoryPostProcessor -> {
BeanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
通过运行后处理器在打印查看结果可以发现bean1、bean2 也注册进去了:
我也可以看一下我们获得的后处理器名字和后处理器实例:
Map<String, BeanFactoryPostProcessor> beans = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
beans.forEach((k, v) -> System.out.println(k + "====" + v));
结果和上面对比可以发现两个后处理器就是上面其中俩:
后面的@Autowired不生效也是一样配置,只是类型不一样:前面的是对BeanFactory的,这个是对于Bean的;
配置后处理器前:
System.out.println(beanFactory.getBean(Bean1.class).getBean2());
结果为: null 说明没有注入进去;
配置后处理器后:
// Bean 后处理器, 针对 bean 的生命周期的各个阶段提供扩展,例如 @Autowired @Resource ...
beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
System.out.println(beanFactory.getBean(Bean1.class).getBean2());
结果正常 :
在这个子实现类中Bean的实例化是在调用时才进行实例化,也就是懒汉(下面代码可以变为恶汉式):
// 这个方法可以让单例的bean提前实例化 而不是默认的 在用到的时候在实例化
beanFactory.preInstantiateSingletons();
后处理的排序
当出现这个的时候是执行哪个呢?
@Resource
@Autowired
private Bean2 bean2;
答案是 @Autowired,原因是在后处理器Map中@Autowired更靠前,其原因是在后处理器中维护着一个值,用来保持一个顺序,靠前的就先调用。
如果需要也可以进行调整。
其中维护的值如下图所示类似: