最近的工作是迁移一个历史遗留的工件(本文称之为工件A),首先需要梳理这个工件的消费者。初步计划按照下面步骤进行:
- 在代码搜索引擎(例如zoekt)里搜索:
- 关键词:工件A的java文件头部的import包名
- 文件类型:java 然后将所有结果的工程名进行排重,得到工件A的所有消费者工程。
Q:为什么不能直接搜索
pom.xml
文件中搜索工件A的名称呢?A:因为存在工件A的消费者工件传递依赖工件A的情况,此种方法不能覆盖传递依赖的场景🥹
- 使用
Intellij IDEA
打开每个消费者工程,依次查看工件A中的服务接口(interface)的使用,菜单Navigatie>Declaration or Usages
- 记录工件A的服务接口存在被使用的方法(后续实现对应的替换接口)
🤨不过看第2、3个步骤看起来挺花时间的,还有其他办法吗?
目前想到的其他办法就是从编译器日志下手,查得可以使用-verbose
选项,来实现:
Uses verbose output, which includes information about each class loaded and each source file compiled.
下面通过一个demo来演示:
使用maven创建工件A:
➜ mvn archetype:generate \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DarchetypeVersion=RELEASE \ -DgroupId=demo.a \ -DartifactId=demo-a \ -Dversion=0.0.1-SNAPSHOT \ -DinteractiveMode=false
然后添加dto、service类:
➜ tree src/main/java/ src/main/java/ └── demo └── a ├── dto │ ├── ProductDto.java │ └── StockDto.java └── service ├── IProductService.java └── impl └── ProductServiceImpl.java 5 directories, 4 files
install 到本地仓库:
➜ mvn install
使用maven创建消费者工件:
➜ mvn archetype:generate \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DarchetypeVersion=RELEASE \ -DgroupId=demo.consumer \ -DartifactId=demo-consumer \ -Dversion=0.0.1-SNAPSHOT \ -DinteractiveMode=false
在pom.xml添加
工件A的依赖
:<dependency> <groupId>demo</groupId> <artifactId>demo-a</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
在App类main方法使用
demo.a.service.IProductService
:package demo.consumer; import demo.a.dto.ProductDto; import demo.a.service.IProductService; import demo.a.service.impl.ProductServiceImpl; /** * Hello world! */ public class App { public static void main(String[] args) { final IProductService productService = new ProductServiceImpl(); final ProductDto productDto = productService.getProductById("1"); // 注意点1 System.out.println(productDto.price); } }
在pom.xml的
maven-compiler-plugin
配置javac参数-verbose
:<plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <compilerArgs> <arg>-verbose</arg> </compilerArgs> </configuration> </plugin>
构建并且将javac日志重定向到文件
javac.log
:➜ mvn clean compile 2>javac.log
查看文件javac.log,不难发现使用到的服务接口类及dto类都在日志中:
➜ grep -nF /demo/a/ javac.log 5:[loading /Users/zenuo/.m2/repository/demo/demo-a/0.0.1-SNAPSHOT/demo-a-0.0.1-SNAPSHOT.jar(/demo/a/dto/ProductDto.class)] 6:[loading /Users/zenuo/.m2/repository/demo/demo-a/0.0.1-SNAPSHOT/demo-a-0.0.1-SNAPSHOT.jar(/demo/a/service/IProductService.class)] 7:[loading /Users/zenuo/.m2/repository/demo/demo-a/0.0.1-SNAPSHOT/demo-a-0.0.1-SNAPSHOT.jar(/demo/a/service/impl/ProductServiceImpl.class)]
🧐回到java代码中的注意点1
:这种写法显式import了demo.a.dto.ProductDto
,若换成不显式import的写法,日志中是否仍然存在demo.a.dto.ProductDto
呢?现在将代码改为如下:
package demo.consumer;
import demo.a.service.IProductService;
import demo.a.service.impl.ProductServiceImpl;
/**
* Hello world!
*/
public class App {
public static void main(String[] args) {
final IProductService productService = new ProductServiceImpl();
System.out.println(productService.getProductById("1").price);
}
}
构建并且将javac日志重定向到文件javac.log.1
:
➜ mvn clean compile 2>javac.log.1
查看javac.log.1,是仍然存在的,只是位置不同:
➜ grep -nF /demo/a/ javac.log.1
5:[loading /Users/zenuo/.m2/repository/demo/demo-a/0.0.1-SNAPSHOT/demo-a-0.0.1-SNAPSHOT.jar(/demo/a/service/IProductService.class)]
6:[loading /Users/zenuo/.m2/repository/demo/demo-a/0.0.1-SNAPSHOT/demo-a-0.0.1-SNAPSHOT.jar(/demo/a/service/impl/ProductServiceImpl.class)]
17:[loading /Users/zenuo/.m2/repository/demo/demo-a/0.0.1-SNAPSHOT/demo-a-0.0.1-SNAPSHOT.jar(/demo/a/dto/ProductDto.class)]
实例代码demo.zip
参考
- Java Platform, Standard Edition Tools Reference
- trying to capture javac output in bash shell
- How to create an empty multi module Maven project?
(248 words)