目录
- BeanFactory
- 怎么使用Sprng提供的容器去注册一个Bean对象(BeanFactory工厂)
- 总结
BeanFactory
怎么使用Sprng提供的容器去注册一个Bean对象(BeanFactory工厂)
重点:Spring容器,例如Beanfactory其实并没有很多的功能,Spring之所以功能这么强大是因为一些后处理器
仅使用BeanFactory容器注入Bean对象
Config.class
@Configuration
static class Config {
@Bean
public Bean1 bean1() {
return new Bean1();
}
@Bean
public Bean2 bean2() {
return new Bean2();
}
}
Bean1
@Slf4j
static class Bean1 {
public Bean1() {
log.debug("构造 Bean1()");
}
}
Bean2
@Slf4j
static class Bean2 {
public Bean2() {
log.debug("构造 Bean2()");
}
}
主启动类测试
public class TestBeanFactory {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// bean 的定义(即bean的一些描述信息,包含class:bean是哪个类,scope:单例还是多例,初始化、销毁方法等)
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
beanFactory.registerBeanDefinition("config", beanDefinition);
// 打印BeanFactory中Bean
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println(name);
}
Config bean = beanFactory.getBean(Config.class);
System.out.println("获取的bean对象为:"+bean);
}
测试结果
存在的问题:
- 从beanfactory工厂中打印的bean信息只有
config
,并没有bean1
和bean2
的信息,说明@Bean
注解没有被处理
使用BeanFactory容器+bean工厂后处理器注入bean对象
给BeanFactory工厂添加常用处理器
// 给 BeanFactory添加一些常用的后处理器,让它具备解析@Configuration、@Bean等注解的能力
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
打印一下常用的后处理器
// BeanFactory 后处理器主要功能,补充了一些 bean 的定义
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
System.out.println(beanFactoryPostProcessor);
});
打印结果
从bean工厂中取出BeanFactory的后处理器,并且执行这些后处理器
// 从bean工厂中取出BeanFactory的后处理器,并且执行这些后处理器
// BeanFactory 后处理器主要功能,补充了一些 bean 的定义
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
System.out.println(beanFactoryPostProcessor);
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
测试结果
Config bean = beanFactory.getBean(Config.class);
System.out.println("获取的bean对象为:"+bean);
Bean1 bean1 = beanFactory.getBean(Bean1.class);
System.out.println("获取的bean对象为:"+bean1);
Bean2 bean2 = beanFactory.getBean(Bean2.class);
System.out.println("获取的bean对象为:"+bean2);
新增Inter接口及两个实现类Bean3、Bean4,修改Bean1
interface Inter {
}
@Slf4j
static class Bean3 implements Inter {
public Bean3() {
log.debug("构造 Bean3()");
}
}
@Slf4j
static class Bean4 implements Inter {
public Bean4() {
log.debug("构造 Bean4()");
}
}
@Slf4j
static class Bean1 {
@Autowired
private Inter inter;
public Inter getInter() {
return inter;
}
public Bean1() {
log.debug("构造 Bean1()");
}
}
问题一:
能够获取Bean1实例对象,但是调用它的getInter
方法获取不到inter
对象,为空
Inter inter = beanFactory.getBean(Config.class).bean1().getInter();
System.out.println("获取的bean对象为:"+inter);
解决方法:从BeanFactory中取出之前添加的后处理器并执行
// 要想@Autowired、@Resource等注解被解析,还要添加Bean的后处理器,可以针对Bean的生命周期的各个阶段提供扩展
// 从bean工厂中取出Bean的后处理器,并且执行这些后处理器
// BeanFactory 后处理器主要功能,补充了一些 bean 的定义
beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
beanFactory.addBeanPostProcessors(beanFactory.getBeansOfType(BeanPostProcessor.class).values());
问题二:
从BeanFactory取出@Autowired
注解对应的后处理器,执行后处理器,执行结果如下:
解决方案:使用@Autowired
注解注入Bean对象时,如果声明的是接口类型,那么声明的变量名要是对应的实现类名称
@Autowired
private Inter bean3;
public Inter getInter() {
return bean3;
}
@Autowired
@Qualifier("bean3")
private Inter inter;
public Inter getInter() {
return inter;
}
@Resource(name = "bean3")
private Inter inter;
public Inter getInter() {
return inter;
}
上述三种方式均可以解决上述异常的问题。
总结
beanFactory 不会做的事
- 不会主动调用BeanFactory的后处理器
- 不会主动添加Bean的后处理器
- 不会主动初始化单例(懒加载)
- 不会解析BeanFactory,还不会解析 ${}, #{}