Spring-2 BeanFactory的实现

一般平时用到的都是BeanFactory的实现类,而BeanFactory最重要的实现类就是DefaultListableBeanFactory。
首先我们创建一个DefaultListableBeanFactory的实例对象,这样我们的容器就能拿到了。
在这里插入图片描述
刚开始创建好BeanFactory,他内部是没有任何bean的,所以我们需要往里面添加一些bean的定义,一开始添加的不是bean对象,因为bean对象是spring帮我们创建的,所以我们是告诉容器我们bean的定义,然后他会通过bean的定义,来创建对应的bean对象。

那什么是bean的定义呢,其实就是BeanDefinition对象,用来描述这个bean长什么样,有哪些特征,比如bean的类型,是单例还是多例,有没有初始化和销毁方法等,所以bean的定义就是去封装了这些描述信息,然后spring后面就会根据这些描述信息来把bean创建好。

这里BeanDefinition对象和bean对象的关系就像是我们class对象和实例对象的关系一样,一个是通过class对象来new具体的实例对象,一个是通过BeanDefinition对象来创建bean对象。

下面就来创建一个BeanDefinition对象(后面简称bd)

创建之前我们先创建3个类Config、Bean1、Bean2
在Config中用@Bean定义了两个类 Bean1和Bean2,并且给他们提供了各自的构造方法,并且打印了信息,方便看到他们的创建时机
又在Bean1中使用@Autowired注入了Bean2
在这里插入图片描述

然后通过BeanDefinitionBuilder类来创建Config类的bd
在这里插入图片描述
创建的时候需要指定bean的类型(这里是Config类)和scope,创建完成之后,通过beanFactory的registerBeanDefinition方法把它注册到spring中
在这里插入图片描述
注册时需要指定一个bean的名字,后面获取bean时需要用到。
然后我们启动,看看beanFactory里面是不是注册了Config的bd
在这里插入图片描述
可以看到我们定义的config的bd已经在beanFactory的beanDefinitionMap中了。

BeanFactory 后置处理器

但是现在有个问题,我们在config类中用@bean注解向spring中注册了2个类,但是这里看到并没有。也就是说@Configuration和@Bean并没有生效,说明现在的beanFactory没有解析这些注解的能力,下面就来看看是谁提供的解析这些注解的功能。

我们先调一个工具类AnnotationConfigUtils的registerAnnotationConfigProcessors方法,这个方法的作用就是给beanFactory添加一些常用的beanFactory后置处理器,给他添加一些扩展功能。
查看这个方法的源码可以看到,添加了一些后置处理器
在这里插入图片描述
然后我们可以看到beanFactory中又多了5个bd
在这里插入图片描述
这都是一些spring内置的后置处理器
比如internalConfigurationAnnotationProcessor,看名字就知道他是用来处理Configuration注解的,加了他之后就会去解析Configuration类以及里面的@bean注解,然后把bean1、bean2补充到spring里。
但是现在看到其实bean1 bean2还没有被添加到spring中,这是因为我们还只是添加了这几个后置处理器,还没有使用他们,我们需要先拿到这些后置处理器,
由于这些后置处理器都是同样的类型,所以我们通过beanFactory.getBeansOfType来获取到BeanFactoryPostProcessor类型的类
在这里插入图片描述
拿到他们之后我们逐一执行他们,就可以对beanFactory作出一些扩展。
在这里插入图片描述
扩展的效果就是会解析Configuration注解和这个类里面的@bean注解。
启动之后我们在来看看
在这里插入图片描述

这时候就能看到bean1 bean2已经在我们的beanFactory中了。这些后置处理器后面会详细讲解。
这里就可以了解到beanFactory本身的功能其实没有那么丰富,很多功能是通过beanFactory后置处理器来实现的。
所以BeanFactory 后置处理器主要功能就是补充了一些 bd。

Bean 后置处理器

接下来我们把bean1 bean2拿出来使用试试,可以通过beanFactory.getBean方法获取bean1和bean2,在控制台打印一下
在这里插入图片描述
可以看到bean1创建成功,但是bean2是null,说明@Autowired的注入功能没用生效。

@Autowired的注入也是一个扩展功能,他是由另外一些后置处理器来完成的,我们刚刚讲的BeanFactory 后置处理器是补充了一些bd。
但是要做依赖注入的话,就会用到bean的后置处理器。那么bean的后置处理器在哪呢?

其实刚刚我们添加常用后置处理器的时候已经添加进去了,
就是internalAutowiredAnnotationProcessor,它的作用就是来解析@Autowired和@value注解的。
还有一个internalCommonAnnotationProcessor,他是用来解析@Resource注解的。
这种就叫做bean的后置处理器,他和BeanFactory 后置处理器有什么不一样呢,他是针对每个bean的生命周期,比如bean的创建,依赖注入,初始化这些阶段,提供一些扩展功能。

跟上面BeanFactory 后置处理器一样,现在他们还没工作,所以需要把他们拿出来,然后添加到bean工厂,接下来getBean的时候就会进入bean的生命周期,然后就会调用我们添加的后置处理器。
在这里插入图片描述
然后我们再来启动一下
在这里插入图片描述
可以看到bean1和bean2都成功的执行了构造方法。说明@Autowired注解被成功解析。这就是bean后置处理器的功能。

疑问

这里有个疑问
在这里插入图片描述
前面已经把后置处理器添加到了BeanFactory,为什么后面还要添加一次?
这是因为第一步只是把这里后置处理器添加到了BeanFactory,他们也只是一个一个的bd,
第二步才是让他们和BeanFactory建立了联系,这样才知道BeanFactory需要用到哪些后置处理器。

初始化单例的时机

现在有个问题,我们的bean是在容器启动的时候就初始化了还是在使用的时候初始化的呢?
我们打印一下看看
在这里插入图片描述
可以看到,是在我们调用getbean方法,使用到bean的时候才去初始化的,而并不是一开始就初始化完成的。
对于这种单例对象,我们一般希望在使用之前就把他创建好,所以需要调用beanFactory.preInstantiateSingletons()方法,来吧这些单例对象提前创建好,而不是到使用的时候才去创建。
加上这个方法后再试试
在这里插入图片描述
可以看到在使用之前这些bean就已经提前创建好了。所以说默认是不会提前创建单例对象。

总结

beanFactory有些事他是不会主动去做的

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

到这里可以发现BeanFactory 是一个基础的容器,很多功能他都没有加入进来,需要我们手动去加。
所以一般推荐使用ApplicationContext,他已经自动加入了这些功能。
下一篇文章我们就来看看ApplicationContext的实现。

公众号同步更新

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值