-
什么是BeanFactory?
是ApplicationContext的父接口
Spring的核心容器,主要的ApplicationContext实现(或者组合)了它的功能

![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WApTu30A-1657012593065)(https://secure2.wostatic.cn/static/6BAL5Dn9e6jCErS9EVMbUj/image.png)]](https://i-blog.csdnimg.cn/blog_migrate/cbd4878778206ca15f87c1e2896912ba.png)
单例的bean存储在singletonObjects中
-
BeanFactory的作用
控制反转,基本的依赖注入,直至Bean的生命周期的各种功能,都有它实现

DefaultSingletonBeanRegistry中的singletonObjects存放了单例的对象
查看singletonObjects中的存储内容
private void getSingletonObjects(AnnotationConfigWebApplicationContext context) {
try {
Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
singletonObjects.setAccessible(true);
BeanFactory parentBeanFactory = context.getBeanFactory();
Object o = singletonObjects.get(parentBeanFactory);
System.out.println(o);
// Map<String, Object> map= (Map<String, Object>)singletonObjects.get(parentBeanFactory);
// map.forEach((k,v)->{
// System.out.println(k + "=" + v);
// });
} catch (Exception e){
e.printStackTrace();
}
}
-
ApplicationContext与BeanFactory的区别?
从上面的类图中可以发现ApplicationContext还集成了资源处理类,获取配置信息,还可发送事件
private void getResource(AnnotationConfigWebApplicationContext context) {
try {
Resource[] resources = context.getResources("classpath:application.properties");
for (Resource resource : resources) {
System.out.println(resource);
}
System.out.println(context.getEnvironment().getProperty("java_home"));
System.out.println(context.getEnvironment().getProperty("server.port"));
//容器之间使用
context.publishEvent(new UserRegisterEvent(context));
} catch (IOException e) {
e.printStackTrace();
}
}
任一spring组件都可一处理发布时的事务。**观察者模式**

-
BeanFactory的实现
BeanFactory可以使用registerBeanDefinition进行获取bean的定义。使用后处理器BeanFactoryPostProcessor进行对BeanFactory的扩展,补充bean的定义
public class TestBeanFactory {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//bean的定义(class,scope,初始化,销毁)
//先获取对象定义的关信息
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).getBeanDefinition();
//打bean定义放在beanFactory中
beanFactory.registerBeanDefinition("config",beanDefinition);
String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
//打印beanFactory中的bean定义名字,获取beanFactory中的此时只会打印config。使用@bean注解的类并没有生效
//beanFactory并没有处理注解的能力
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
System.out.println("---------------------------------------------------------------------------");
//给beanFactory添加常用的后处理器,后处理器进行beanFactory的扩展
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
String[] beanDefinitionNameArray = beanFactory.getBeanDefinitionNames();
//此时打印的是spring内置的处理器,Bean1对象不在容器中
for (String beanDefinitionName : beanDefinitionNameArray) {
System.out.println(beanDefinitionName);
}
System.out.println("---------------------------------------------------------------------------");
//拿到符合类型的所有后处理器,使用处理器进行解析
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().stream().forEach(item->{
item.postProcessBeanFactory(beanFactory);
});
String[] beanDefinitionNameArrays = beanFactory.getBeanDefinitionNames();
//此时打印的是spring内置的处理器,Bean1对象不在容器中
for (String beanDefinitionName : beanDefinitionNameArrays) {
System.out.println(beanDefinitionName);
}
System.out.println("---------------------------------------------------------------------------");
}
@Configuration
static class Config{
@Bean
public Bean1 bean1(){
return new Bean1();
}
@Bean
public Bean2 bean2(){
return new Bean2();
}
}
static class Bean1{
@Autowired
private Bean2 bean2;
public Bean1() {
System.out.println("bean1");
}
}
static class Bean2{
public Bean2() {
System.out.println("bean2");
}
}
}
运行结果如下
spring使用懒加载。当对象使用时才会创建。调用beanFactory.preInstantiateSingletons();会预先加载单例对象
// //获取bean1对象
// Bean2 bean2 = beanFactory.getBean(Bean1.class).getBean2();
// System.out.println(bean2);
// //此时打印bean2为空,证明@Autowired注解未启用,可以使用bean 后处理器进行解决
// System.out.println("---------------------------------------------------------------------------");
//bean 后处理器 和 beanFactory 后处理器作用不同,针对bean声明周期的各个阶段提供扩展如:@Autowired
beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
Bean2 bean22 = beanFactory.getBean(Bean1.class).getBean2();
System.out.println(bean22);
System.out.println("---------------------------------------------------------------------------");

beanFactory不会主动做的事情,
- 不会主动添加BeanFactory 后处理器
- 不会主动添加Bean 后处理器,bean后处理器会有排序的逻辑
- 不会主动初始化单例
- 不会解析${ }和#{}
但ApplicationContext已经做好了这些解析
如果@Autowired和@Resource同时在一个对象变量使用时,@Autowired先生效。查看AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory)源码可以发现;
bean后处理器有排序逻辑
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pp1KoOcS-1657013058914)(https://secure2.wostatic.cn/static/pqK8FBZ88BeE7Z9m8r8TCz/image.png)]](https://i-blog.csdnimg.cn/blog_migrate/d021dd3c6fb93257824705cb601b4618.png)
如果想要改变顺序可以添加比较器

本文深入探讨了BeanFactory,它是Spring核心容器的一部分,负责控制反转和依赖注入。介绍了DefaultSingletonBeanRegistry中的singletonObjects如何存储单例对象,并对比了ApplicationContext与BeanFactory的区别,包括ApplicationContext在资源处理和事件发送上的额外功能。此外,详细阐述了BeanFactory的实现方式,如registerBeanDefinition和BeanFactoryPostProcessor,以及Spring的懒加载机制。最后讨论了BeanFactory与ApplicationContext在处理Bean后处理器和属性占位符解析的差异,并指出在@Autowired和@Resource注解共存时的处理顺序。

147

被折叠的 条评论
为什么被折叠?



