7.父子容器问题以及懒加载

51 阅读2分钟

当使用父子容器之后,如果去父容器中查找Bean,那么就单纯的在父容器中查找Bean;如果是去子容器中查找Bean,那么就会先在子容器中查找,找到了就返回,没找到就继续去父容器中查找,直到找到了位置(把父容器都找完了,还是没有的话,就会抛异常)

假设我有一个多模块项目,其中有商家模块和客户模块,商家模块和客户模块都是角色管理RoleService,项目结构如下图。

image.png

现在consumer和merchant中都有一个RoleService类,然后在各自的配置文件中,都将该类注册到Spring容器中

image.png

配置文件如下:

image.png

这两个Bean 同名,在Admin模块中,同时依赖consumer和merchant,同时加载这两个配置文件执行后会抛出如下问题:

image.png

image.png

这是找不到consumer。RoleService服务,但是另外一个找到了,这是默认情况下,后面定位的同名Bean 把前面的覆盖了,所以有一个Bean就找不到了。 如果不允许Bean的覆盖,增加如下配置:

image.png

会直接报错,Bean的定义冲突了。如果要解决这个办法,就是父子容器。

image.png

对于上面的问题,我们可以将consumer和merchant配置成关系兄弟或者父子关系,就能很好的解决这个问题。

image.png

这里针对consumer和merchant 分别创建了容器,这种容器关系就是兄弟容器,这两个兄弟有共同的parent就是ctx,现在可以在各个容器中获取到自己的Bean。 需要注意的是,上面的结构,子容器可以获取到parent的Bean,但是无法获取到兄弟容器的Bean,即如果consumer中引用了merchant中的Bean,那么上面的配置会有问题。

image.png

首先创建两个容器,分别是parent和child,然后为child容器设置parent,设置完成要刷新child容器。 现在我们就可以从parent容器中获取本来就存在的Bean, 也可以从child容器中去获取child容器中本来存在的Bean 或者Parent的Bean。

特殊情况:

并不是所有的Bean方法都支持父子关系查找,有的方法只能子啊当前容器中查找,并不会去父容器中查找:

image.png

带层级关系的接口:

image.png

不带层级关系的接口:

image.png

懒加载:

单例一般会直接被加载: 1.添加lazy-init属性

image.png

2.使用factoryBean ,天然具备懒加载的能力。FactoryBean这个类本身,默认是提前加载的,但是这个类的getObject方法是在第一次获取Bean的时候才执行的。

3.注解