对于多模块开发会遇到的问题——父子容器

springmvc中使用父子容器

就是controller层交给一个spring容器加载,其他的service和dao层交给另外一个spring容器加载,web.xml中有这块配置,这两个容器组成了父子容器的关系
通常我们使用springmvc的时候,采用3层结构(可以只使用一个容器),controller层,service层,dao层;父容器中会包含dao层和service层(一般是controller层调用其他层的处理),而子容器中包含的只有controller层;这2个容器组成了父子容器的关系,controller层通常会注入service层的bean
多模块的例子
系统中有2个模块:module1和module2,两个模块是独立开发的,module2会使用到module1中的一些类,module1会将自己打包为jar提供给module2使用,我们来看一下这2个模块的代码

模块1

放在module1包中

Service1

package com.javacode2018.lesson002.demo17.module1;

import org.springframework.stereotype.Component;

@Component
public class Service1 {
    public String m1() {
        return "我是module1中的Servce1中的m1方法";
    }
}

Service2

package com.javacode2018.lesson002.demo17.module1;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Service2 {

    @Autowired
    private com.javacode2018.lesson002.demo17.module1.Service1 service1; //@1

    public String m1() { //@2
        return this.service1.m1();
    }

}

扫描类扫描

@ComopnentScan

模块2
Service1

package com.javacode2018.lesson002.demo17.module2;

import org.springframework.stereotype.Component;

@Component
public class Service1 {
    public String m2() {
        return "我是module2中的Servce1中的m2方法";
    }
}

Service3

package com.javacode2018.lesson002.demo17.module2;

import com.javacode2018.lesson002.demo17.module1.Service2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Service3 {
    //使用模块2中的Service1
    @Autowired
    private com.javacode2018.lesson002.demo17.module2.Service1 service1; //@1
    //使用模块1中的Service2
    @Autowired
    private com.javacode2018.lesson002.demo17.module1.Service2 service2; //@2

    public String m1() {
        return this.service2.m1();
    }

    public String m2() {
        return this.service1.m2();
    }

}
@1:使用module2中的Service1
@2:使用module1中的Service2

测试类


public class ParentFactoryTest {

    @Test
    public void test1() {
        //定义容器
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        //注册bean
        context.register(Module1Config.class, Module2Config.class); //@1
        //启动容器
        context.refresh();
    }
}
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'service1' for bean class [com.javacode2018.lesson002.demo17.module2.Service1] conflicts with existing, non-compatible bean definition of same name and class [com.javacode2018.lesson002.demo17.module1.Service1]

输出结果,bean冲突了,一般解决这种问题,可以通过修改bean名,或者别名的方式来,但是对于多模块项目,工作量就会很大了
比较好的解决办法
创建spring容器的时候,可以给当前容器指定一个父容器
BeanFactory的方式

//创建父容器parentFactory
DefaultListableBeanFactory parentFactory = new DefaultListableBeanFactory();
//创建一个子容器childFactory
DefaultListableBeanFactory childFactory = new DefaultListableBeanFactory();
//调用setParentBeanFactory指定父容器
childFactory.setParentBeanFactory(parentFactory);

ApplicationContext的方式

//创建父容器
AnnotationConfigApplicationContext parentContext = new AnnotationConfigApplicationContext();
//启动父容器
parentContext.refresh();

//创建子容器
AnnotationConfigApplicationContext childContext = new AnnotationConfigApplicationContext();
//给子容器设置父容器
childContext.setParent(parentContext);
//启动子容器
childContext.refresh();

父子容器特点

1、父容器和子容器是相互隔离的,他们内部可以存在名称相同的bean
2、子容器可以访问父容器中的bean,而父容器不能访问子容器中的bean
3、调用子容器的getBean方法获取bean的时候,会沿着当前容器开始向上面的容器进行查找,直到找到对应的bean为止
4、子容器中可以通过任何注入方式注入父容器中的bean,而父容器中是无法注入子容器中的bean

修改会的测试类

@Test
public void test2() {
    //创建父容器
    AnnotationConfigApplicationContext parentContext = new AnnotationConfigApplicationContext();
    //向父容器中注册Module1Config配置类
    parentContext.register(Module1Config.class);
    //启动父容器
    parentContext.refresh();

    //创建子容器
    AnnotationConfigApplicationContext childContext = new AnnotationConfigApplicationContext();
    //向子容器中注册Module2Config配置类
    childContext.register(Module2Config.class);
    //给子容器设置父容器
    childContext.setParent(parentContext);
    //启动子容器
    childContext.refresh();

    //从子容器中获取Service3
    Service3 service3 = childContext.getBean(Service3.class);
    System.out.println(service3.m1());
    System.out.println(service3.m2());
}

输出结果

我是module1中的Servce1中的m1方法
我是module2中的Servce1中的m2方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值