暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

BeanFactory与ApplicationContext的区别

代码小裁缝 2022-06-12
1552

今天想和大家聊聊Spring容器中的两大核心接口的区别,它们是BeanFactory和ApplicationContext,字面意思理解区别,有区别则必然有,虽然说都可以当作Sping容器,但是层级不一样,其中ApplicationContext是BeanFactory的子接口,也就是说ApplicationContext继承了BeanFactory接口,接口之间的继承,也就是那些方法的继承,我们来看看它的继承关系图。

那么ApplicationContext接口作为BeanFactory的派生,除了提供了BeanFactory所具有的功能外,还提供了更完整的框架功能,那么他们之间具体有着怎么样的区别呢?

一、ApplicationContext有更完整的功能:

  • 它继承了MessageSource,支持国际化,统一资源文件访问的方式。

  • 提供在监听器中注册bean事件。

  • 同时加载多个配置文件。

  • 载入多个上下文。


二、加载方式的不同:

这里我们来通过一个完整代码案例来看一下这两种方式的区别,首先我们先起一个三层架构的项目,创建好我们需要各种文件,



👆dao层的实现类,方法很简单,被调用到的时候打印一句方法正在执行即可,因为不是大型开发项目,我们只做演示,能达到效果即可。👆dao层的实现类,方法很简单,被调用到的时候打印一句方法正在执行即可,因为不是大型开发项目,我们只做演示,能达到效果即可。


👆Service层的实现类,方法一样简单,其中有一个IUserDao类型的属性dao,然后就是针对于接口方法以及无参构造里面输出我们的打印语句。


👆Controller实现类,方法和Service层基本一致,这里不再赘述,为了后续方便测试,这里我采用xml文件形式注入Bean,我们主要看一下Spring的配置xml文件中的Bean标签配置。


Xml文件中依次按照我们的Dao层到Controller层的调用来顺序填写Bean标签,这里需要注意的是,我在Bean标签内部手动装配了它的依赖,以确保测试过程中没有问题,接下来我们开始分别测试BeanFactory和ApplicationContext这两种加载形式对于Bean的创建时机有什么不一样,首先我们测BeanFactory。


这里呢我们可以看得见,先是读取完了配置文件,并没有读取完配置文件后立即创建Bean对象。后面是因为我获取了Bean实例,调用了Controller的方法,所以才开始创建Bean对象,它要等到调用getbean方法的时候才开始实例化对象,并且它的创建顺序并不是按照我们传统意义上代码从上往下执行的顺序一行一行创建的。因为我们获取了Controller对象的实例,然后调用了Controller对象的方法,所以尽管我们在xml文件里,Controller的标签是写在最底下的。但是因为我们调用的是Controller的方法,它就会优先创建Controller的对象,然后因为Controller的对象的创建需要Service依赖,所以接着创建Service,又因为创建Service又要解决Dao依赖,所以它的创建对象的顺序就是Controller--->Servicer--->Dao,依次解决依赖问题后依次调用方法实现。也就是说它采用延迟加载的形式来注入Bean的,只有用到某个Bean的时候,才会对该Bean进行加载实例化,这样的话,程序运行速度会比较快一些。但是它有一个缺点,就是假如说,我们Spring配置的时候,这个Bean的某一个对象没有注入,那么BeanFactory加载后,我们如果没有调用到这个Bean的话,那就发现不了这个问题,这里不妨我们来测一测。


这里我在xml文件中把Controller的依赖Service注释掉,然后我们测一下BeanFactory的创建调用对象方法的过程。


这里我在xml文件中把Controller的依赖Service注释掉,然后我们测一下BeanFactory的创建调用对象方法的过程,发现和预期一样,在调用getbean方法的时候就会报错,这个缺点在读取配置文件完成后没有显示出来。

接下来我们把xml文件重新恢复好,准备测试ApplicationContext,遵循单一变量原则,别的参数不动,保持数据一致。


我们可以看得见ApplicationContext是按照我们的xml文件中的Bean标签顺序来进行实例化创建的,并且在配置文件读取完成的时候,已经加载完成了所有的Bean,这一点在创建Bean的时机上和BenaFactory是明显不同的,接下来我们调换一下Bean标签的顺序,看看我们调换Bean标签的顺序后,会不会改变它的加载顺序。


这里呢我选择把Controller标签放在第一个,然后我们来测试一下,看看会不会影响到具体的Bean的创建顺序。



       这个的创建顺序呢,和我们Bean标签写的顺序不一样,它是先创建Controller,然后解决Service依赖,紧接着,它发现了Service依赖Bean里面也有一个依赖,这样它得先解决Service内部的依赖后,才能解决Controller的Service依赖,也就是说创建Bean是从外往内的,依赖解决是从内往外的,这是它区别于Beanfactory的地方。我们再来测一测改变注释掉依赖属性后,它的Bean创建会不会有什么变化,这次我们的注释方式和之前测BeanFactory的方式一样,xmlBean标签的方式和最开始一样按照Dao--->Servicer--->Controller的顺序,然后注释掉Controller的标签Service依赖,紧接着进行测试。




因为它是在配置文件读取完的时候就加载出来了所有Bean,所以这次我们就只看容器加载完后的Bean,这里呢我们可以很明显的看到,Controller的对象并没有被成功实例化出来,这是因为什么呢,因为它的依赖没有注入,导致他无法被成功加载,从总体加载时机上的区别大致就是这样。
    

三、PostProcessor的方式不同:


它们都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但是两者的区别是,Beanfactory需要手动注册,而ApplicationContext则是自动注册。


四、创建方式不同:

BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader。


五、总结:


1:Beanfactory和ApplicationContext的框架功能完整度不同,后者相较于前者功能更加强大

2:加载Bean的时机不同,Beanfactory是读取配置文件后等待调用的时候才创建Bean,而ApplicationContext是读取完配置文件的时候,它就实例化了Bean,相较于Beanfactory,ApplicationContext唯一不足的是占用内容空间,当配置的Bean较多的时候,程序启动迟缓。

3:PostProcessor的方式不同,一个手动操作,一个自动注册。

4:创建方式上的不一致。

文章转载自代码小裁缝,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论