JDK APT(Annotation Processing Tool) 编译时注解处理器

博文目录

文章目录

  • javac
  • Annotation Processing
    • How Annotation Processing Works
    • Compilation Environment and Runtime Environment
  • maven-compile-plugin
  • 对 Maven pom 中配置注解处理器的理解
  • Lombok, MapStruct, MyBatis-Flex 说明
    • 测试
    • 只在 dependencies 中配置 Lombok 和 MapStruct
    • 在 compile 插件中配置 Lombok 和 MapStruct
  • 结论


javac

The javac Command - processor-path

先看下面几个 javac 命令参数的说明

  • -proc:[none, only, full]
    • Controls whether annotation processing and compilation are done. -proc:none means that compilation takes place without annotation processing. -proc:only means that only annotation processing is done, without any subsequent compilation. If this option is not used, or -proc:full is specified, annotation processing and compilation are done.
    • 控制是否完成注解处理和编译。-proc:none 表示在没有注解处理的情况下进行编译。-proc:only 意味着只进行注解处理,而不进行任何后续编译。如果未使用此选项,或指定 -proc:full 则完成注解处理和编译。
  • -processor class1[,class2,class3...]
    • Names of the annotation processors to run. This bypasses the default discovery process.
    • 要运行的注解处理器的名称。这绕过了默认的发现进程。
  • --processor-module-path path
    • Specifies the module path used for finding annotation processors.
    • 指定用于查找注解处理器的模块路径。
  • --processor-path path or -processorpath path
    • Specifies where to find annotation processors. If this option is not used, then the class path is searched for processors.
    • 指定在何处找到注解处理器。如果未使用此选项,则在类路径中搜索处理器。

大致意思是, javac 命令有 注解处理编译 的功能, 常规流程是先处理注解, 待完成后再执行编译操作

默认情况下, javac 会从类路径中搜索注解处理器(如何搜索下面说), 然后执行其注解处理逻辑, 最后执行编译流程

这里说的注解处理功能就是 APT, 全称 Annotation Processing Tool. 具体的注解处理逻辑由注解处理器定义, 通常都是生成一些新的源码, 源码参与后续编译, 从而增强对应类与功能, 常见的有 Lombok, MapStruct, MyBatis-Flex 等

Annotation Processing

The javac Command - Annotation Processing

javac 编译命令提供了注解处理的直接支持, 相关 API 被定义在 javax.annotation.processing 和 javax.lang.model 包和子包中

How Annotation Processing Works

除非使用 -proc:none 选项禁用注解处理,否则编译器将搜索任何可用的注解处理器。可以使用 -processorpath 选项指定搜索路径。如果未指定路径,则使用用户类路径。处理器通过搜索路径上名为 META-INF/services/javax.annotation.Processing.Processor 的服务提供者配置文件定位(就是判断各个 jar 包中是否有这个文件)。这些文件应该包含要使用的任何注解处理器的名称,每行列出一个。或者,也可以使用 -processor 选项显式指定处理器(就是说 -processorpath 和 -processor 两个参数二选一)。

在扫描命令行上的源文件和类以确定存在哪些注解之后,编译器将查询处理器以确定它们处理哪些注解。找到匹配的注解时调用处理器。处理器可以声明它所处理的注解,在这种情况下,不会进一步尝试为这些注解寻找任何处理器(就是说一旦找到某注解的一个处理器就不再继续寻找)。在所有注解都被声明处理之后,编译器不会搜索其他处理器(就是说如果有多余的处理器没有匹配到注解, 这些处理器也不会被调用了)。

如果任何处理器生成新的源文件,那么就会进行另一轮注解处理: 扫描所有新生成的源文件,并像以前一样处理注解。在前几轮调用的任何处理器也在后面的所有轮调用。这种情况一直持续到不生成新的源文件为止。

在没有生成新源文件的情况下进行一轮后,将最后一次调用注解处理器,以便它们有机会完成剩余的任何工作。最后,除非使用 -proc:only 选项,否则编译器将编译原始文件和所有生成的源文件。

如果使用注解处理器生成要包含在编译中的其他源文件,则可以指定用于新生成的文件的默认模块,以便在不生成模块声明时使用。在这种情况下,使用 --default-module-for-create-files 选项。

Compilation Environment and Runtime Environment

Javac 分析源文件和之前编译的类文件中的声明时,使用的编译环境不同于用来执行 javac 本身的运行时环境。尽管很多 javac 选项和 Java 启动程序的类似命名选项之间存在一定的相似性,比如 --class-path--module-path 等等,但是重要的是要理解,一般来说 javac 选项只影响源文件编译的环境,并不影响 javac 本身的操作。

在使用注解处理器时,编译环境和运行时环境之间的区别是显著的。虽然注解处理器处理编译环境中存在的元素(声明) ,但是注解处理器本身是在运行时环境中执行的。如果注解处理器依赖于不在模块中的库,那么可以将这些库以及注解处理器本身放在处理器路径上。(–processor-path 选项)。如果注解处理器及其依赖项位于模块中,则应改为使用处理器模块路径。(–processor-module-path 选项)。当这些不足够时,可能需要提供进一步的运行时环境配置。

  • 如果从命令行调用 javac,则可以通过在选项前面加上 -J 将选项传递给底层运行时。
  • 您可以直接启动 Java 虚拟机的一个实例,并使用命令行选项和 API 来配置一个环境,在这个环境中可以通过其中一个 API 调用 javac。

maven-compile-plugin

Maven 编译插件提供了 APT 支持

  • annotationProcessorPaths
    • 指定注解处理器的多个搜索路径。如果指定了,编译器将只在这些类路径元素中检测注解处理器。如果省略,则使用默认类路径来检测注解处理器。检测本身依赖于 annotationProcessors 配置。
    • 每个类路径元素都使用它们的 Maven 坐标 (groupId、 artifactId、 version)指定。
  • annotationProcessorPathsUseDepMgmt
    • 在解析注解处理器路径的传递依赖关系时,是否使用 Maven 依赖关系管理部分。
    • 此标志不启用/禁用从依赖项管理部分解析注解处理程序路径版本的能力。它只影响那些顶级路径的传递依赖关系的解析。
  • annotationProcessors
    • 要运行的注解处理程序的名称。只适用于 JDK 1.6 +,如果没有设置,则应用默认的注解处理程序发现过程。

对 Maven pom 中配置注解处理器的理解

javac 执行过程中, 先扫描源文件以确定存在哪些注解, 之后编译器在类路径中逐个检索处理器以确定能处理哪些注解, 然后逐个调用找到的处理器, 循环这些过程直到不再生成新的源文件. 最后才是执行编译

  • 不指定编译时的注解相关参数, 编译器会在所有类路径中, 逐个找到注解处理器并执行
  • 指定注解处理器的检索路径时, 编译器只会在指定的类路径中, 逐个找到注解处理器并执行

换句话说, 只要把注解处理器配置到 dependencies 标签中即可, 并不需要特地去配置 maven-compile-plugin 的 annotationProcessorPaths, 但是一旦配置了 annotationProcessorPaths, 就需要把所有涉及到的注解处理器都配置过来, 因为编译时只会在配置的类路径中查找注解处理器

类路径, 这里有一个 Maven 编译时的例子, classpath 中, 放在首位的是自己写的类, 然后是根据 pom dependencies 配置的 mapstruct, mapstruct-processor, lombok 这三个依赖包, 编译器会按照这个顺序查找注解处理器
在这里插入图片描述

Lombok, MapStruct, MyBatis-Flex 说明

MyBatis-Flex 和 Lombok、Mapstruct 整合
MapStruct - Can I use MapStruct together with Project Lombok?

Lombok 中, 开发使用的 @Slf4j, @Getter, @Setter 等注解以及处理这些注解的处理器, 都直接放在了同一个 lombok 包中. MapStruct 中, 开发使用的 @Mapper, @Mappers 等注解以及以来的 Mappers 类都放在了 mapstruct 包中, 而处理这些注解的处理器放在了 mapstruct-processor 包中. MyBatis-Flex 中, 开发使用的各种依赖都放在了 mybatis-fles-core 包中, 而自动生成 TableDef 类的处理器放在了 mybatis-flex-processor 包中

MapStruct 依赖 Lombok 生成的 Getter 和 Setter 等方法, MyBatis-Flex 不确定是否依赖 Lombok, 盲猜不依赖

MyBatis-Flex 官网推荐把 lombok, lombok-mapstruct-bidding, mapstruct-processor, mybatis-flex-processor 按先后顺序配置到 Maven Compile 插件的 annotationProcessorPaths 中

而 MapStruct 官网给出的示例代码中, 同样配置到了 Maven Compile 插件的 annotationProcessorPaths 中, 但顺序是 mapstruct-processor, lombok, lombok-mapstruct-binding

根据我们对 APT 的理解, 处理器可以在 dependencies 中配置, 配置到 Maven Compile 插件中也行, 当然, 配置到插件中是有好处的, 检索处理器的速度更快, 也能避免多模块项目或者其他依赖传递造成类路径先后顺序的改变

通过做几个小实验, 来理解编译器是如何 逐个 在类路径或指定的处理器检索路径检索处理器的

测试

新建一个测试的 Maven 项目, 用于测试 Lombok 和 MapStruct 是否受 pom.xml 配置的影响

提供 User 和 UserDto 两个类, 提供 UserMapper 用于 User 转 UserDto

通过修改 lombok 和 mapstruct-processor 的先后位置, 判断先后顺序是否影响注解处理器工作

结果是, 会影响

  • 当只配置 dependencies 没配置 maven-compile-plugin 的 annotationProcessorPaths
    • 当 lombok 在 mapstruct-processor 前时, 可正常编译通过
@Getter
@Setter
@ToString
public class User {
    private String username;
}

@Getter
@Setter
@ToString
public class UserDto {
    private String username;
}

@Mapper
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
    @Mapping(source = "username", target = "username")
    UserDto userToUserDto(User user);
}

只在 dependencies 中配置 Lombok 和 MapStruct

当 lombok 放在 mapstruct-processor 前面时, 可以正常处理注解并编译通过

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.32</version>
    </dependency>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>1.5.5.Final</version>
    </dependency>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-processor</artifactId>
        <version>1.5.5.Final</version>
    </dependency>
</dependencies>

当 lombok 放在 mapstruct-processor 后面时, 报错 No property named "username" exists in source parameter(s). Type "User" has no properties.

<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>1.5.5.Final</version>
    </dependency>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-processor</artifactId>
        <version>1.5.5.Final</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.32</version>
    </dependency>
</dependencies>

当 lombok 放在 mapstruct-processor 后面, 但提供了 lombok-mapstruct-binding 时, 可以正常处理注解并编译通过

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.5.5.Final</version>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.5.5.Final</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.32</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok-mapstruct-binding</artifactId>
    <version>0.2.0</version>
</dependency>

当 lombok, mapstruct-processor, lombok-mapstruct-binding 任意排序时, 可以正常处理注解并编译通过

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok-mapstruct-binding</artifactId>
    <version>0.2.0</version>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.5.5.Final</version>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.5.5.Final</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.32</version>
</dependency>

由此可猜测编译过程中, 类路径参数的组织是按照 pom dependencies 从上到下的顺序来的, 且 lombok-mapstruct-binding 的作用是取消 MapStruct 和 Lombok 强制顺序依赖, 让 lombok, mapstruct-processor, lombok-mapstruct-binding 可以配置任意顺序

在 compile 插件中配置 Lombok 和 MapStruct

当 lombok 放在 mapstruct-processor 前面时, 可以正常处理注解并编译通过

<path>
  <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.32</version>
</path>
<path>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.5.5.Final</version>
</path>

当 lombok 放在 mapstruct-processor 后面时, 报错 No property named "username" exists in source parameter(s). Type "User" has no properties.

<path>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.5.5.Final</version>
</path>
<path>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.32</version>
</path>

当 lombok 放在 mapstruct-processor 后面, 但提供了 lombok-mapstruct-binding 时, 可以正常处理注解并编译通过

<path>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.5.5.Final</version>
</path>
<path>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.32</version>
</path>
<path>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok-mapstruct-binding</artifactId>
    <version>0.2.0</version>
</path>

测试结果与只在 dependencies 中配置完全一致

结论

APT, 编译时注解处理器, 在编译器编译源码前, 编译器会按照类路径的顺序扫描注解处理器, 注解处理器主要负责生成各种附加源码, 处理器流程执行结束后, 编译器会将手写源码与生成源码(生成在 target/generated-sources 目录下)一同编译

默认情况下, 编译器会从用户类路径下逐个查找注解处理器, 但如果指定了注解处理器查找路径参数, 则只从指定的路径中逐个查找

Maven pom dependencies 配置依赖的顺序就是最终用户类路径的顺序

maven-compile-plugin 中 annotationProcessorPaths 配置注解处理器的顺序就是最终查找注解处理器的顺序, 优先级高于 dependencies, 有这个配置就不会按照 dependencies 配置的类路径查找注解处理器了, 且这种方式配置的注解处理器的查找速度应该会快一点

处理器 mapstruct-processor 需要依赖 处理器 lombok 的执行结果, 依赖其生成的 Getter 和 Setter 方法, Maven pom dependencies 中 lombok 要放在 mapstruct-processor 前面. 因为 Maven 项目可能有多层嵌套模块, 也可能存在复杂的依赖传递, 在各种因素的影响下, 最终 Maven 执行计划中, dependencies 里 lombok, mapstruct-processor 的顺序可能与预期不一致, 导致编译失败

Lombok 提供了另一个处理器 lombok-mapstruct-binding, 其作用是取消 MapStruct 和 Lombok 强制顺序依赖, 让 lombok, mapstruct-processor, lombok-mapstruct-binding 可以配置任意顺序

又因为, 将注解处理器配置到编译插件中速度会快一点, 所以后续 Lombok 和 MapStruct 建议如下配置方式, 先后顺序随意即可

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.32</version>
    </dependency>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>1.5.5.Final</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.12.0</version>
            <configuration>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                        <version>1.18.32</version>
                    </path>
                    <path>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok-mapstruct-binding</artifactId>
                        <version>0.2.0</version>
                    </path>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>1.5.5.Final</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/620148.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【网络安全】适合新手的CTF靶场合集(非常详细)零基础入门到精通,收藏这一篇就够了

前言 经常会有粉丝朋友询问大白&#xff0c;如何打CTF比赛&#xff0c;有没有适合新手的CTF靶场&#xff1f; 今天呢大白就给粉丝朋友分享一下&#xff0c;我整理得可能没有那么全&#xff0c;这里的合集主要还是面对新手。做题贵精不在多&#xff0c;好好练习每一题&#xf…

STM32 PWM 计数器模式和对齐

STM32 PWM 计数器模式和对齐 1. TIM高级定时器简介2. TIM计数模式2.1 向上计数2.2 向下计数2.3 中心对齐模式&#xff08;向上/向下计数&#xff09;2.4 重复计数 3. PWM输出模式3.1 举例看下PWM中心对齐模式&#xff0c;设置参数如下&#xff1a; 4. FOC中PWM相关设置说明4.1 …

其他的 框架安全:Apache Shiro 漏洞序列.(CVE-2016-2807)

什么是 Apache Shiro Apache Shiro 是一个强大且易用的Java安全框架&#xff0c;它为应用程序提供了身份验证、授权、加密和会话管理等常见的安全功能。漏洞大多会发生在登录处&#xff0c;返回包里包含remeberMedeleteMe字段.&#xff08; Shiro 这个属于第三方的&#xff0c…

Linux线程(三)死锁与线程同步

目录 一、什么是死锁 死锁的四个必要条件 如何避免死锁 避免死锁算法 二、Linux线程同步 三 、条件变量 1、条件变量基本原理 2、条件变量的使用 3、条件变量使用示例 为什么 pthread_cond_wait 需要互斥量? 一、什么是死锁 死锁是计算机科学中的一个概念&#xff0c;…

Qt---绘图和绘图设备

一、QPainter绘图 绘图事件 void paintEvent() 声明一个画家对象&#xff0c;OPainter painter(this) this指定绘图设备 画线、画圆、画矩形、画文字 设置画笔QPen 设置画笔宽度、风格 设置画刷QBrush 设置画刷风格 代码示例&#xff1a; #includ…

买一手股指期货跌多少会爆仓?

当指数下跌导致持有的股指期货合约价值减少&#xff0c;而你的保证金账户中的资金不足以维持原有的保证金要求时&#xff0c;期货公司会要求你追加保证金&#xff0c;即所谓的“追加保证金通知”。如果投资者无法及时补足保证金&#xff0c;期货公司则有权强制平仓&#xff0c;…

【Linux】磁盘文件

思维导图 学习目标 了解磁盘的物理结构和存储结构&#xff0c;并将其存储结构进行抽象&#xff01;&#xff01; 一、了解一下磁盘及其物理结构 1.1 计算机只认识二进制 什么是二进制&#xff1f;&#xff1f;0&#xff0c;1是被规定出来的&#xff0c;在计算机里面我们用高低…

SAP 控制已转采购订单的PR不允许删除简介

SAP系统中采购申请当被转成采购订单后&#xff0c;在采购申请中会关联到对应已生生成的采购订单&#xff0c;如下图中可以看到采购申请对应的采购订单 当日常操作中用户在创建完采购申请后&#xff0c;当PR转成PO后仍然可以将采购申请的行项目进行删除&#xff0c;显然这个操作…

『拼多多、淘宝、抖音、小红书等卖家』4个有效动作,走出成单低谷期

对于拼多多、淘宝、抖音、小红书等平台的卖家来说&#xff0c;走出成单低谷期需要一系列有效的动作。以下是店雷达四个建议&#xff1a; 一、选品优化 1、深入市场研究&#xff1a;了解当前市场趋势、消费者需求和潜在的市场空白。使用各种工具&#xff0c;如店雷达选品功能&…

Python深度学习基于Tensorflow(2)Tensorflow基础

文章目录 基本操作数据转换和数据生成操作形状数据提取和保存变量Numpy和Tensorflow的比较 计算图静态图动态图自动图 自动微分使用Tensorflow 实现回归 首先是Tensorflow的安装&#xff0c;由于可能会出现版本冲突&#xff0c;最好在conda环境安装&#xff0c;同时&#xff0c…

华为OD机试 - 密码输入检测(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试…

leetcode经典例题之环形队列

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 目录 1、题目展示2、问题分析3、完整代码展示4、结语 1、题目展示 在拿到题目时&#xff0c;通…

前端动态旋转地球背景

效果图 贴下源码 <template><div class"map-bg"><div class"canvas" id"canvs"></div><canvas class"canvasxk" id"canv"></canvas></div> </template><script setup …

如何快速提取出一个文件里面全部指定类型的文件的全部路径

首先&#xff0c;需要用到的这个工具&#xff1a; 度娘网盘 提取码&#xff1a;qwu2 蓝奏云 提取码&#xff1a;2r1z 打开工具&#xff0c;切换到第五个模块&#xff0c;文件批量复制模块&#xff08;快捷键&#xff1a;Ctrl5&#xff09; 点击右边的“搜索添加”按钮&#…

20 分页:较小的表

目录 简单的解决方案&#xff1a;更大的页 混合方法&#xff1a;分页和分段 多级页表 详细的多级示例 超过两级 ​编辑地址转换过程&#xff1a;记住TLB 反向页表 将页表交换到磁盘 之前提到的一个问题&#xff1a;就是页表太大&#xff0c;假设一个 32 位地址空间&…

高中数学:平面向量-基本概念

一、定义 有方向&#xff0c;且有大小的量&#xff0c;就叫向量 与之对应的是&#xff0c;数量&#xff0c;只有大小&#xff0c;没有方向 例如 A B → \mathop{AB}\limits ^{\rightarrow} AB→ a → \mathop{a}\limits ^{\rightarrow} a→ 二、相关性质 相等 大小相同…

(超详细讲解)实现将idea的java程序打包成exe (新版,可以在没有java的电脑下运行,即可以发给好朋友一起玩)

目录 实现打包到exe大概步骤 工具准备 1.将java程序文件打包成jar文件 2.准备好jre文件 3.使用exe4j软件打包好 4.最终打包 实现打包到exe大概步骤 1.打包需要满足的条件&#xff1a;将java文件转成jar文件的工具exe4j、 以及需要满足jdk1.8以上&#xff08;因安装exe4…

【必看】Spring系列面试题

Spring Core Container, AOP, Data Access, Web... 基础 1. 简单介绍Spring 一款开源的轻量级 Java 开发框架&#xff0c;旨在提高开发人员的开发效率以及系统的可维护性。Spring 支持 IoC&#xff08;Inversion of Control:控制反转&#xff09; 和 AOP(Aspect-Oriented Pro…

网络隔离状态下,如何可以安全高效地进行研发文件外发?

研发部门的数据传输通常需要保证数据的安全性、完整性和保密性&#xff0c;尤其是当涉及到公司的核心技术、产品设计、源代码等重要信息时。研发文件外发&#xff0c;即研发资料的外部传输&#xff0c;通常涉及到公司的核心技术和商业机密&#xff0c;因此需要采取严格的安全措…

动态NAT

在上一章静态NAT中我们提过了&#xff0c;静态NAT只能一对一映射&#xff0c;无法有效缓解IPV4地址池紧张的问题&#xff0c;那么我们今天来学习一个新的技术——动态NAT&#xff0c;来解决这个问题。 第一章 1.1 动态NAT工作流程 动态NAT基于地址池来实现私有地址和公有地址的…