当前位置: 首页 > news >正文

2.4 构建模块化应用


第4章:构建模块化应用

模块化应用是 JDK 9 的核心特性之一,通过模块化系统(Project Jigsaw)实现代码的强封装和显式依赖管理。本章详细讲解如何从零构建一个模块化应用,包括模块定义、编译、打包、运行及调试。


4.1 模块化应用开发流程
  1. 定义模块:编写 module-info.java 声明模块元数据。
  2. 组织代码:按模块化结构组织源代码。
  3. 编译模块:使用 javac 编译模块。
  4. 打包模块:将模块打包为模块化 JAR。
  5. 运行模块:使用 java 命令运行模块化应用。
  6. 调试与优化:使用工具(如 jdeps)分析依赖关系。

4.2 模块化应用实战
场景:构建一个简单的模块化应用,包含以下模块:
  1. com.utils:工具模块,提供字符串处理工具。
  2. com.user:用户模块,依赖 com.utils,导出用户模型。

4.3 步骤详解
步骤1:定义模块
  1. com.utils 模块

    • 模块描述符
      // com.utils/module-info.java
      module com.utils {exports com.utils; // 导出工具包
      }
      
    • 工具类
      // com.utils/com/utils/StringUtil.java
      package com.utils;public class StringUtil {public static String capitalize(String s) {return s.substring(0, 1).toUpperCase() + s.substring(1);}
      }
      
  2. com.user 模块

    • 模块描述符
      // com.user/module-info.java
      module com.user {requires com.utils; // 依赖工具模块exports com.user.model; // 导出用户模型包
      }
      
    • 用户类
      // com.user/com/user/model/User.java
      package com.user.model;import com.utils.StringUtil;public class User {private String name;public User(String name) {this.name = StringUtil.capitalize(name);}public String getName() { return name; }
      }
      

步骤2:组织代码结构
src/
├── com.utils/
│   ├── module-info.java
│   └── com/utils/
│       └── StringUtil.java
└── com.user/├── module-info.java└── com/user/└── model/└── User.java

步骤3:编译模块

使用 javac 编译模块,指定模块源路径和输出目录:

javac -d out --module-source-path src --module com.utils,com.user

编译后的目录结构

out/
├── com.utils/
│   ├── module-info.class
│   └── com/utils/
│       └── StringUtil.class
└── com.user/├── module-info.class└── com/user/└── model/└── User.class

步骤4:打包模块

将模块打包为模块化 JAR:

# 打包 com.utils 模块
jar --create --file mods/com.utils.jar -C out/com.utils .# 打包 com.user 模块
jar --create --file mods/com.user.jar -C out/com.user .

打包后的目录结构

mods/
├── com.utils.jar
└── com.user.jar

步骤5:运行模块化应用

使用 java 命令运行模块化应用,指定模块路径和主模块:

java --module-path mods -m com.user/com.user.model.User

步骤6:调试与优化
  1. 使用 jdeps 分析依赖

    jdeps --module-path mods -s mods/com.user.jar
    # 输出示例:
    com.user -> com.utils
    com.user -> java.base
    
  2. 生成模块图

    jdeps --module-path mods --dot-output dots mods/com.user.jar
    
    • 生成 dots/com.user.dot 文件,可用 Graphviz 工具生成依赖图。

4.4 模块化应用最佳实践
1. 最小化模块导出
  • 仅导出必要的包,隐藏实现细节。
  • 示例:
    module com.myapp {exports com.myapp.api; // 仅导出API包
    }
    
2. 使用传递依赖
  • 通过 requires transitive 声明传递依赖,避免重复依赖。
  • 示例:
    module com.myapp {requires transitive com.utils; // 传递依赖
    }
    
3. 适配反射框架
  • 使用 opens 开放反射访问权限,支持 Spring/Hibernate 等框架。
  • 示例:
    module com.myapp {opens com.myapp.internal to spring.core; // 允许Spring反射访问
    }
    
4. 生成定制化 JRE
  • 使用 jlink 生成仅包含所需模块的最小化 JRE。
  • 示例:
    jlink --module-path $JAVA_HOME/jmods:mods \--add-modules com.user,java.base \--output myapp-runtime
    

4.5 常见问题与解决
问题解决方案
模块未找到(Module not found)检查模块路径(--module-path)是否包含依赖模块,确认 requires 声明正确。
无法访问非导出包使用 exports 导出包或 opens 开放反射访问权限。
生成的 JRE 缺少必要模块检查 jlink--add-modules 参数是否包含所有依赖模块。

4.6 总结

构建模块化应用是 JDK 9 的核心能力,通过模块化系统实现强封装和显式依赖管理,显著提升了代码的安全性和可维护性。开发者应掌握模块定义、编译、打包及运行的全流程,并结合工具链(如 jdepsjlink)优化应用性能与兼容性。

相关文章:

2.4 构建模块化应用

第4章:构建模块化应用 模块化应用是 JDK 9 的核心特性之一,通过模块化系统(Project Jigsaw)实现代码的强封装和显式依赖管理。本章详细讲解如何从零构建一个模块化应用,包括模块定义、编译、打包、运行及调试。 4.1 模…...

DeepSeek:从入门到精通

在人工智能飞速发展的今天,DeepSeek作为一款备受瞩目的AI工具,正以其强大的功能和开源理念改变着我们的生活和工作方式。本文将带你深入了解DeepSeek,从基础入门到进阶应用,助你快速掌握这一前沿工具。 文末有详细资料可下载 文末…...

JAVA学习第二天

ArryList的构造方法和添加方法 01。构造方法的<>里面可以放数据类型 02. add&#xff08;&#xff09;可以直接在后面加入数据&#xff0c;也可以指定下标的插入元素。 ArrayList的常用方法 ArrayList存储对象 在Java中&#xff0c;System.out.println()可以打印基本数据…...

DevOps工具链概述

1. DevOps工具链概述 1.1 DevOps工具链的定义 DevOps工具链是支持DevOps实践的一系列工具的集合&#xff0c;这些工具覆盖了软件开发的整个生命周期&#xff0c;包括需求管理、开发、测试、部署和运维等各个环节。它旨在通过工具的集成和自动化&#xff0c;打破开发与运维之间…...

windows系统远程桌面连接ubuntu18.04

记录一下自己在配置过程中遇到的问题&#xff0c;记录遇到的两大坑&#xff1a; windows系统通过xrdp远程桌面连接ubuntu18.04的蓝屏问题。参考以下第一章解决。 同一局域网内网段不同的连接问题。参考以下第三章解决&#xff0c;前提是SSH可连。 1. 在ubuntu上安装xrdp 参考&…...

kafka动态监听主题

简单版本 import org.springframework.beans.factory.annotation.Autowired; import org.springframework.kafka.core.ConsumerFactory; import org.springframework.kafka.listener.ConcurrentMessageListenerContainer; import org.springframework.kafka.listener.Containe…...

Python虚拟环境管理工具 pyenv

情景 我现在在部署一个python 项目&#xff0c;需要用到Python 3.10。但是我本地已经有了一个3.12解释器&#xff0c;有没有一种方法&#xff0c;可以管理python 环境&#xff0c;还可以随意切换。怎么做&#xff1f; window 安装pyenv-win 使用 PowerShell&#xff08;以管…...

网络安全产品架构图 网络安全相关产品

一、信息安全产品分类 背景 美国将网络和信息安全产品分了9类&#xff1a;鉴别、访问控制、入侵检测、防火墙、公钥基础设施、恶意程序代码防护、漏洞扫描、取证、介质清理或擦除。中国公安部将网络和信息安全产品分了7类&#xff1a;操作系统安全、数据库安全、网络安全、病毒…...

C++ 实践扩展(Qt Creator 联动 Visual Studio 2022)

​ 这里我们将在 VS 上实现 QT 编程&#xff0c;实现如下&#xff1a; 一、Vs 2022 配置&#xff08;若已安装&#xff0c;可直接跳过&#xff09; 点击链接&#xff1a;​​​​​Visual Studio 2022 我们先去 Vs 官网下载&#xff0c;如下&#xff1a; 等待程序安装完成之…...

如何实现Deepseek的本地部署并集成本地知识库?

1、下载并配置Deepseek环境 https://blog.csdn.net/kxg6666/article/details/145593346?spm1001.2014.3001.5501 2、安装AnythingLLM AnythingLLM | The all-in-one AI application for everyone 如官网下载较慢&#xff0c;本文最后提供夸克离线下载链接。下载后默认安装…...

vue学习笔记8

Pinia基础使用 - 计数器案例 定义Store&#xff08;state action&#xff09; 组件使用Store getters实现 Pinia中的 getters 直接使用 computed函数 进行模拟, 组件中需要使用需要把 getters return出去 action异步实现 编写方式&#xff1a;异步action函数的写法和组件…...

【自学笔记】Vue基础知识点总览-持续更新

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Vue重点知识点总览一、Vue基础1. Vue简介2. MVVM设计思想3. 响应式数据绑定4. 组件化开发 二、Vue核心特性1. 虚拟DOM2. 模板语法3. 计算属性与监听属性 三、Vue高级…...

ETL的使用(sqoop):数据导入,导出

ETL ETL: 是数据抽取&#xff08;Extract&#xff09;、数据转换&#xff08;Transform&#xff09;和数据加载&#xff08;Load&#xff09;的整个过程 常用的ETL工具 sqoop 1.Apache Sqoop 是 Apache 软件基金会旗下的一个开源项目&#xff0c;旨在帮助用户高效地在 Hado…...

【核心特性】从鸭子类型到Go的io.Writer设计哲学

在编程语言的设计中&#xff0c;鸭子类型和接口设计是两种非常重要的理念。它们都强调了对象的行为和能力&#xff0c;而非其具体的类型或继承关系。Go 语言的io.Writer 接口是这种设计理念的典型代表&#xff0c;它通过简洁的接口定义&#xff0c;实现了强大的功能和灵活性。 …...

多模态模型详解

多模态模型是什么 多模态模型是一种能够处理和理解多种数据类型&#xff08;如文本、图像、音频、视频等&#xff09;的机器学习模型&#xff0c;通过融合不同模态的信息来提升任务的性能。其核心在于利用不同模态之间的互补性&#xff0c;增强模型的鲁棒性和准确性。 如何融合…...

Go 语言里中的堆与栈

在 Go 语言里&#xff0c;堆和栈是内存管理的两个重要概念&#xff0c;它们在多个方面存在明显差异&#xff1a; 1. 内存分配与回收方式 栈 分配&#xff1a;Go 语言中&#xff0c;栈内存主要用于存储函数的局部变量和调用信息。当一个函数被调用时&#xff0c;Go 会自动为其…...

八、OSG学习笔记-

前一章节&#xff1a; 七、OSG学习笔记-碰撞检测-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/145558132?spm1001.2014.3001.5501 一、了解OSG图元加载显示流程 本章节代码&#xff1a; OsgStudy/wids CuiQingCheng/OsgStudy - 码云 - 开源中国https:…...

本地部署【LLM-deepseek】大模型 ollama+deepseek/conda(python)+openwebui/docker+openwebui

通过ollama本地部署deepseek 总共两步 1.模型部署 2.[web页面] 参考官网 ollama:模型部署 https://ollama.com/ open-webui:web页面 https://github.com/open-webui/open-webui 设备参考 Mac M 芯片 windows未知 蒸馏模型版本:deepseek-r1:14b 运行情况macminim2 24256 本地…...

网络分析工具—WireShark的安装及使用

Wireshark 是一个广泛使用的网络协议分析工具&#xff0c;常被网络管理员、开发人员和安全专家用来捕获和分析网络数据包。它支持多种网络协议&#xff0c;能够帮助用户深入理解网络流量、诊断网络问题以及进行安全分析。 Wireshark 的主要功能 数据包捕获与分析&#xff1a; …...

MobaXterm的图形化界面支持:原理与分辨率问题解决

1. 概述 MobaXterm 是一款功能强大的远程访问工具&#xff0c;支持SSH、RDP、X11、VNC等多种协议&#xff0c;并内置了强大的图形界面支持&#xff0c;让用户能够在远程操作Linux/Unix系统时&#xff0c;享受到类似本地桌面的流畅体验。 与传统的SSH客户端不同&#xff0c;Mo…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

Python实现简单音频数据压缩与解压算法

Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中&#xff0c;压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言&#xff0c;提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...