3-Spring的分模块开发(Context的分级机制)

本文介绍了一种利用Spring框架进行大型项目分模块开发的方法,通过设置不同层级的配置文件来解决bean命名冲突问题,实现各模块间的解耦,并提供了一个核心类ContextHelper的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

spring 分模块开发


使用不同的两个 context.xml 配置文件new出来的Context就是不同的Context他们之间不可以进行Bean的互访.只能访问相同的父级Context.

背景
      我们一般采用spring+Struts +ibatis的开发模式,使用spring统管业务bean,当项目很大时, 面临一个bean命名冲突问题,如果和struts一样,采取分模块的方式,不同的模块有自己的命名空间,将会避免几个并行开发的子 系统 或模块共用一套bean配置文件时id产生重名的问题。

简单方案
     整个系统所使用的公共bean,例如数据源、事务管理、iBatis或Hibernate 的引擎、国际化资源文件等,放在一个root context文件中, 构造一个 ApplicationContext实例,作为各子模块的父,这里就看出Spring 设计 上的易扩展性了,ApplicationContext的构造子允许通过一个父实例来创建。
   
    核心类 ContextHelper ,作为管理器类,如下:
    
 public class ContextHelper {

    // 不同的环境有不同的配置文件

    private static Map _contexts ; //环境容器
    private static ApplicationContext _rootContext; //根环境
    private static final String ROOT_CONTEXT = "conf/rootContext.XML"; //根环境的配置文件
 
   static {
      _contexts = new HashMap();
      try{
        _rootContext = new ClassPathXmlApplicationContext(ROOT_CONTEXT); //创建根环境
      } catch (Exception e) {
        throw new ContextException(e);
      }
   }

  //获取一个Bean, 第一个参数为环境名 另一个参数为Bean名
  public static synchronized Object getBean(String configName, String beanName) {
      ApplicationContext context = getApplicationContext(configName);
      Object bean = context.getBean(beanName);
      return bean;
   }
  

    //lazyload 根据context名从Map中获取一个context
   private static synchronized ApplicationContext getApplicationContext(String  configName) {
     if(_contexts.containsKey(configName)) {
       return (ApplicationContext) _contexts.get(configName);
     }

     //这里规定了模块配置文件的命名规则
     String moduleConfigFile = "conf/" + configName + ".bean.xml";  //规则
     String [] configs = { moduleConfigFile};

     //传入一个配置文件和根Context

      ApplicationContext context = new ClassPathXmlApplicationContext(configs,_rootContext); //创建子Context
     _contexts.put(configName, context);

     return context;
   }
 
   //消息资源文件管理

  public static String getMessage(String key,Object[] arg,Locale l){
    return _rootContext.getMessage(key,arg,l);
  } 
}

   需要注意的一点是,各子模块bean配置文件中,如果引用根配置中的bean,不可以使用local属性了,请使用bean=“dataSource“,一开始没注意到这个问题,总报错,无法正确合并,我调试了好久才发现。

ToDo

  上述方案还比较简陋,主要的隐患在于,各模块之间的通信问题,当前的设计比较适用于各模块耦合度较小的情况,如果有一些bean,供几个模块之间共用,势必也需要提至rootContext.xml中配置,大大增加了根文件的复杂性。
  另外,可供改进处还有一个,每个模块应该允许采用多个bean配置文件,允许将dao、service等tier分开来处理,可以通过建立一个 properties文件,将模块逻辑名与若干配置文件建立映射关系来解决。我得承认,当前的简版方案在context load上有一些hard code的坏气味。
<think>嗯,用户现在问的是关于通用的功能模块和DDD(领域驱动设计)思想。首先,我需要理解这两个概念分别是什么,然后看看它们之间有什么联系。 首先,通用的功能模块,可能指的是在软件开发中经常被重复使用的模块,比如用户管理、权限控制、日志记录这些。这些模块在不同的系统中都可能需要,所以被称为“通用”。用户可能想知道有哪些这样的模块,以及如何设计它们以便于复用。 然后是DDD思想,也就是领域驱动设计。这是一种软件设计方法,强调通过领域模型来指导复杂系统的开发,核心是让业务专家和开发人员共同合作,通过统一的语言(通用语言)来构建模型。DDD包括战略设计和战术设计,比如限界上下文、实体、值对象、聚合根等概念。 用户可能想了解如何将通用的功能模块结合到DDD的设计中,或者在使用DDD时如何设计这些通用模块。也有可能他们想了解DDD本身的一些核心概念,以及如何应用这些概念来设计系统。 接下来需要确定用户的具体需求。他们可能是在进行系统设计,想要采用DDD,同时希望复用一些通用模块,所以需要指导如何结合这两者。或者他们可能对这两者分别感兴趣,但不太清楚它们之间的联系。 需要先解释通用的功能模块有哪些,每个模块的功能和设计要点,然后介绍DDD的核心思想,最后说明如何用DDD的思想来设计这些通用模块,或者这些模块在DDD架构中的位置。 另外,用户之前的提问是关于网站分类和功能总结,现在转向技术设计,可能用户是开发人员或系统设计师,正在规划一个项目,需要技术方面的指导。需要确保回答既全面又不失深度,同时保持结构清晰,易于理解。 可能的误区是,用户可能认为通用功能模块和DDD是独立的,但实际上在DDD中,通用模块可能属于支撑子域或通用子域,需要根据限界上下文来划分。需要解释清楚这些概念之间的关系,避免混淆。 需要检查是否有遗漏的关键点,例如DDD中的战术模式如仓储、领域服务、应用服务等如何应用于通用模块的设计,或者如何通过DDD的战略设计来划分系统边界,使得通用模块能够被有效复用。 还要注意用户可能对DDD的术语不太熟悉,需要用简洁的语言解释,避免过于晦涩。同时,结合之前的回答风格,使用清晰的分类和列表,帮助用户逐步理解。</think>以下是关于**通用功能模块**与**DDD(领域驱动设计)思想**的综合介绍,从模块分类到设计原则的逐步解析: --- ### 一、**通用功能模块** 指在多个系统中可复用的业务或技术组件,通常分为以下两类: #### **1. 技术通用模块** **功能定位**: - 提供基础设施支持,与具体业务无关。 **典型模块**: - **用户认证与权限管理** - 功能:登录/注册、角色权限分配(RBAC)、OAuth 集成 - 设计要点:支持多租户、权限动态配置 - **日志与监控** - 功能:操作日志记录、性能监控、错误追踪 - 设计要点:异步写入、日志分级(INFO/ERROR) - **文件存储与分发** - 功能:文件上传/下载、CDN 加速 - 设计要点:支持多种存储后端(OSS、本地) - **消息队列与通知** - 功能:异步任务处理、邮件/SMS 推送 - 设计要点:消息去重、失败重试机制 #### **2. 业务通用模块** **功能定位**: - 服务于特定业务场景,但可跨系统复用。 **典型模块**: - **支付网关集成** - 功能:对接支付宝、微信支付等 - 设计要点:统一支付接口、支持多通道切换 - **地理位置服务** - 功能:地址解析(Geocoding)、路径规划 - 设计要点:缓存高频查询结果 - **数据统计与报表** - 功能:数据聚合、可视化图表生成 - 设计要点:支持自定义维度筛选 --- ### 二、**DDD(领域驱动设计)思想** #### **核心目标** 通过**领域模型**(Domain Model)解决复杂业务问题,强调**业务与技术对齐**。 #### **关键概念** 1. **战略设计**(划分系统边界) - **限界上下文(Bounded Context)**: 定义业务子领域的独立边界,例如将“订单”与“库存”划分为不同上下文。 - **上下文映射(Context Mapping)**: 描述限界上下文间的协作关系,如 *合作关系*(Partnership)或 *客户-供应商*(Customer-Supplier)。 2. **战术设计**(模型实现细节) - **实体(Entity)**: 具有唯一标识的对象(如订单号 `OrderId`)。 - **值对象(Value Object)**: 无唯一标识,通过属性定义(如 `Money` 包含金额与币种)。 - **聚合根(Aggregate Root)**: 控制一组关联对象的一致性(如 `Order` 聚合根管理订单项 `OrderItem`)。 - **领域服务(Domain Service)**: 封装跨聚合的业务逻辑(如 `PaymentService` 处理支付流程)。 - **仓储(Repository)**: 提供聚合根的持久化接口,隔离数据库细节。 #### **DDD 与通用模块的结合** 1. **识别通用子域(Generic Subdomain)** - 将技术通用模块(如权限管理)归类为**支撑子域**,业务通用模块(如支付)归类为**通用子域**。 - 示例:支付模块可作为通用子域,通过 *防腐层(Anti-Corruption Layer)* 隔离外部依赖。 2. **模块化设计原则** - **高内聚低耦合**:每个限界上下文独立部署,通过 API 或事件通信。 - **事件驱动架构**:使用领域事件(Domain Events)解耦模块(如订单创建后触发 `OrderCreatedEvent`)。 3. **代码分层结构** ```plaintext ┌─────────────┐ │ 用户接口层 │ (API/Web) ├─────────────┤ │ 应用层 │ (协调领域逻辑,如 OrderAppService) ├─────────────┤ │ 领域层 │ (实体、值对象、领域服务) ├─────────────┤ │ 基础设施层 │ (数据库、消息队列实现) └─────────────┘ ``` --- ### 三、**实践建议** 1. **明确领域边界** - 通过事件风暴(Event Storming)梳理业务流程,避免模块功能重叠。 2. **抽象通用能力** - 将技术模块(如日志)设计为基础设施层插件,业务模块(如支付)通过限界上下文封装。 3. **技术选型** - 使用框架(如 Spring Boot + Axon Framework)支持 DDD 分层与事件驱动。 --- ### **总结** - **通用模块**需通过标准化接口与高扩展性设计实现复用。 - **DDD** 提供了一种从业务出发的系统设计方法论,通过限界上下文与分层架构降低复杂性。 - 两者结合时,需将通用模块映射到 DDD 的支撑子域或通用子域中,并通过清晰的上下文映射确保协作效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值