0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Spring 应用合并之路(一):摸石头过河

京东云 来源:京东科技 李君 作者:京东科技 李君 2024-10-28 11:11 次阅读

作者:京东科技 李君

公司最近一年在推进降本增效,在用尽各种手段之后,发现应用太多,每个应用都做跨机房容灾部署,则最少需要 4 台机器(称为容器更合适)。那么,将相近应用做一个合并,减少维护项目,提高机器利用率就是一个可选方案。



经过前后三次不同的折腾,最后探索出来一个可行方案。记录一下,分享出来,希望对有相关需求的研发童鞋有所帮助。下面按照四种可能的方案,分别做介绍。另外,为了方便做演示,专门整了两个演示项目:



•diguage/merge-demo-boot — 合并项目,下面简称为 boot。

•diguage/merge-demo-web — 被合并项目,下面简称为 web。



一、Jar 包引用



这个方式,可能是给人印象最容易的方式。仔细思考一下,从维护性的角度来看,这个方式反而是最麻烦的方式,理由如下:



1.web 项目每次更新,都需要重新打包发布新版; boot 项目也需要跟着更新发布。拉一次屎,脱两次裤子。属实麻烦。

2.还需要考虑 web 项目的加载问题,类似下面要描述的,是否共用容器:共用容器 — 这是最容器想到的方式。但是这种方式,需要解决 Bean 冲突的问题。不共用容器 — 这种方式需要处理 web 容器如何加载的问题。默认应该是无法识别。

3.

基于这些考虑,这种方式直接被抛弃了。



二、仓库合并,公用一套容器



这是第一次尝试使用的方案。也是遇到问题最多的方案。



1.将两个仓库做合并。

1.将 web 仓库的地址配置到 boot 项目里: git remote add web git@github.com:diguage/merge-demo-web.git;

2.在 boot 项目里,切出来一个分支: git switch -c web;

3.将 web 分支的提交清空: git update-ref -d HEAD,然后做一次提交;

4.将 web 项目的代码克隆到 web 分支上: git pull --rebase --allow-unrelated-histories web master;注意,这里需要加 --allow-unrelated-histories 参数,以允许不相干的仓库进行合并。

5.从 boot 项目的 master 分支上,切出来一个合并分支: git switch -c merge;

6.将 web 项目向 boot 项目合并: git merge --allow-unrelated-histories web;注意,这里需要加 --allow-unrelated-histories 参数,以允许不相干的仓库进行合并。

7.处理代码冲突,完成合并即可。

2.配置文件的合并于归整。为了防止同名配置文件冲突,需要把 web 项目的配置文件调整到一个文件夹下,这里设定为 web 目录。然后,需要把 web 项目的配置文件,让 boot 可以加载到。这个调整相对简单,只需要一个注解即可 @ImportResource({"classpath:web/spring-cfg.xml"})。

3.调整完配置文件,接着遇到的问题就是上面提到的 Bean 冲突的问题。由于两个项目都访问相同的数据库, Dao 及 Service 层很多很多类都是同名的。另外,在 web 项目里,Dao 是基于 iBATIS 开发的,而在 boot 项目里,DAO 是基于 MyBATIS 开发的。所以,只能给 web 项目的相关代码做重命名(严谨一点是给 Spring Bean 的 beanName 做重命名操作)。这又带来了新问题:原来的项目里,注入方式是根据名称注入的,就需要改动大量的代码,给相关的 Bean 变量做重命名操作。这无形中增加了很多的复杂度和不确定性。



经过不断折腾,这种方式被迫放弃。



三、仓库合并,Spring Boot 父子容器



在经过上述方式折腾后,就想到了另外一个方案:可以考虑使用父子容器的方式来搞。接着就查到了这篇文章: Context Hierarchy with the Spring Boot Fluent Builder API。感觉这种方式挺不错,就尝试了一下。



1.代码合并及文件调整,跟上述步骤类似,这个后面就不再赘述。

2.按照文章中的介绍,使用父子容器的方式来加载两个项目。代码如下:

3.原以为,这种方式属于父子两个容器,即使有同名的 Bean 应该也没有影响。但是,经过实践才发现,上面这个猜测是错误的。Spring Boot 在启动的时候,它背后做了检查,如果两个容器有同名的 Bean,它也会报错。也会带来像上述方式那样的大量重命名。折腾一两天,最后还是放弃了这种寄予厚望的方式。

package com.diguage.demo.boot;

import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

/**
 * @author D瓜哥 · https://www.diguage.com
 */
public class DemoBootApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder()
                .parent(BootConfig.class).web(WebApplicationType.NONE)
                .child(WebConfig.class)
                // 如果有第三个项目,可以作为子容器的兄弟容器加载。
                // .sibling(SiblingConfig.class)
                .run(args);
    }

    @Configuration
    @ImportResource({"classpath:spring-cfg.xml"})
    @ComponentScan(basePackages = "com.diguage.demo.boot")
    public static class BootConfig {
    }

    @Configuration
    @ImportResource({"classpath:web/spring-cfg.xml"})
    public static class WebConfig {
    }
}


Spring Boot 背后是否做了检查,这个是根据报错信息的猜测,没有翻看代码,所以这个猜测有一定的不确定性。有机会翻一下代码,查看一下具体原因。

革命尚未成功,且听下回分解……

下文:Spring 应用合并之路(二):峰回路转,柳暗花明

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • spring
    +关注

    关注

    0

    文章

    336

    浏览量

    14280
收藏 人收藏

    评论

    相关推荐

    java spring教程

    java spring教程理解Spring 实现原理掌握Spring IOC,AOP掌握Spring的基础配置和用法熟练使用SSH开发项目Sprin
    发表于 09-11 11:09

    什么是java spring

    什么是java springSpring是个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成
    发表于 09-11 11:16

    Spring工作原理

    2.AOP的主要原理:动态代理Spring工作原理Spring 已经用过段时间了,感觉Spring是个很不错的框架。内部最核心的就是IOC了,动态注入,让
    发表于 07-10 07:41

    Spring框架的设计理念

    Spring作为现在最优秀的框架之,已被广泛的使用,51CTO也曾经针对Spring框架中的hqC应用做过报道。本文将从另外个视角试图剖析出Sp
    发表于 07-15 08:17

    Spring笔记分享

    框架:高度抽取,可重用代码的种设计高度的通用性多个可重用模块的集合,形成某个领域的整体解决方案Spring => 容器框架包含并管理应用对象的生命周期IOC和SOP容器框架容器 =>
    发表于 11-04 07:51

    Spring认证」Spring Hello World 项目示例

    让我们开始使用 Spring Framework 进行实际编程。在开始使用 Spring 框架编写第个示例之前,您必须确保已按照Spring - 环境设置章节中的说明正确设置了
    发表于 08-17 13:49

    如何通过指针将字符串存放到高128字节?keil该怎样设置?

    ;,str);结果没有显示。在keil里设置了存储模式为large:varabes in PDATA也没用。应该是那里没设置好,以前直用汇编编程没碰到这些事情,现在尝试学习用C51编写,好多地方都在石头
    发表于 10-23 20:30

    spring教程ppt

    主要内容Spring 概述Spring 整体结构Spring实例Spring核心概念介绍控制反转(IOC)依赖注入(DI)
    发表于 09-11 11:00 138次下载
    <b class='flag-5'>spring</b>教程ppt

    Skyworks逆袭靠什么?

    而在2002年由Alpha Industries和Conexant的无线通信部门合并而成的Skyworks则更像个摸着石头过河的无名小辈,直到2009年Skyworks才决定集中精力发展射频前端市场。
    的头像 发表于 05-17 09:19 5284次阅读
    Skyworks逆袭靠什么?

    Spring认证_什么是Spring GraphQL

    GraphQL 支持通过 HTTP 和 WebSocket 的 GraphQL 请求。 HTTP GraphQlHttpHandler 通过 HTTP 请求处理 GraphQL,并委托给 Web 拦截执行请求。有两种变体,种用于 Spring MVC,
    的头像 发表于 08-06 14:30 664次阅读
    <b class='flag-5'>Spring</b>认证_什么是<b class='flag-5'>Spring</b> GraphQL

    Spring认证」什么是Spring GraphQL?

    这个项目建立在 Boot 2.x 上,但它应该与最新的 Boot2.4.x5 相关。 要创建项目,请转到start.spring.io并为要使用的GraphQL传输选择启动器: 启动机 运输 执行
    的头像 发表于 08-10 14:08 774次阅读
    「<b class='flag-5'>Spring</b>认证」什么是<b class='flag-5'>Spring</b> GraphQL?

    为什么要学习SpringSpring核心基础教程详解?

    为什么要学习SpringSpring 框架是个开源的 Java 平台。它最初由 Rod Johnson 编写,并于 2003 年 6 月在 Apache 2.0 许可下首次发布。 Spr
    的头像 发表于 08-11 16:00 568次阅读
    为什么要学习<b class='flag-5'>Spring</b>?<b class='flag-5'>Spring</b>核心基础教程详解?

    Spring认证」Spring IoC 容器

    ,我们将在下章中讨论。 容器通过读取提供的配置元数据来获取有关要实例化、配置和配置哪些对象的指令。数据可以由XML、Java注释或Java代码表示。下图展示了Spring如何工作的高级视图。 IoC
    的头像 发表于 06-28 13:27 710次阅读
    「<b class='flag-5'>Spring</b>认证」<b class='flag-5'>Spring</b> IoC 容器

    Spring认证是什么?

    Spring Certified Professional 2022 Spring Professional认证旨在测试和验证学生对 SpringSpring Boot核心方面的
    的头像 发表于 07-04 10:19 1245次阅读
    <b class='flag-5'>Spring</b>认证是什么?

    Spring Boot 的设计目标

    什么是Spring Boot Spring Boot 是 Spring 开源组织下的个子项目,也是 Spring 组件
    的头像 发表于 10-13 14:56 527次阅读
    <b class='flag-5'>Spring</b> Boot 的设计目标