Archunit的使用

注:开发的编辑器: Intellij Idea,JDK版本是JDK8

    Archunit是什么,官网的英文介绍很好,建议阅读原文,"ArchUnit is a free, simple and extensible library for checking the architecture of your Java code using any plain Java unit test framework. That is, ArchUnit can check dependencies between packages and classes, layers and slices, check for cyclic dependencies and more"。
简单来说,它是代码格式、类之间的依赖关系检查工具。

使用介绍

进入官网
点击右上角的"User Gruide"
之后就可以看到它的英文教程文档。

1.pom.xml中加入依赖

List-1 最重要的是archunit-junit4依赖
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>com.tngtech.archunit</groupId>
    <artifactId>archunit-junit4</artifactId>
    <version>0.9.1</version>
    <scope>test</scope>
</dependency>

2.添加规则

直接上代码了,如下List-2所示,按项目情况,修改自己的"@AnalyzeClasses的packages值"
import javax.persistence.Entity;

import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.junit.ArchUnitRunner;
import com.tngtech.archunit.lang.ArchRule; import org.junit.runner.RunWith; import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
import static com.tngtech.archunit.library.GeneralCodingRules.NO_CLASSES_SHOULD_ACCESS_STANDARD_STREAMS;
import static com.tngtech.archunit.library.GeneralCodingRules.NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS;
import static com.tngtech.archunit.library.GeneralCodingRules.NO_CLASSES_SHOULD_USE_JAVA_UTIL_LOGGING; /**
 * @author dmj1161859184@126.com 2018-09-14 23:03
 * @version 1.0
 * @since 1.0
 */
@RunWith(ArchUnitRunner.class) // Remove this line for JUnit 5!!
@AnalyzeClasses(packages = "com.mjduan.project") //要扫描的package
public class ArchunitTest {     /** dao下的类应该以Dao结尾 */
    @ArchTest
    public static final ArchRule DAOs_must_reside_in_a_dao_package = classes()
            .that()
            .haveNameMatching(".*Dao")
            .should()
            .resideInAPackage("..dao..")
            .as("DAOs should reside in a package '..dao..'");     /** controller下的类应该以Controller结尾 */
    @ArchTest
    public static final ArchRule CONTROLLERs_must_reside_in_a_dao_package = classes()
            .that()
            .haveNameMatching(".*Controller")
            .should()
            .resideInAPackage("..controller..")
            .as("DAOs should reside in a package '..dao..'");     /** util下的类应该以Util结尾 */
    @ArchTest
    public static final ArchRule UTILs_must_reside_in_a_dao_package = classes()
            .that()
            .haveNameMatching(".*Util")
            .should()
            .resideInAPackage("..util..")
            .as("DAOs should reside in a package '..dao..'");     /** 有Entity注解的类,应该在domain或者entity包下 */
    @ArchTest
    public static final ArchRule entities_must_reside_in_a_domain_package = classes()
            .that()
            .areAnnotatedWith(Entity.class)
            .should()
            .resideInAnyPackage("..domain..", "..entity..");     /** 接口类,应该以I开头 */
    @ArchTest
    public static final ArchRule interface_className_must_start_with_I = classes()
            .that()
            .areInterfaces()
            .should()
            .haveSimpleNameStartingWith("I")
            .as("Interface should start with I");     /** service下的类,只能被controller下或者时service下的类访问 */
    @ArchTest
    public static final ArchRule services_should_only_be_accessed_by_controllers_or_other_services = classes()
            .that()
            .resideInAPackage("..service..")
            .should()
            .onlyBeAccessed()
            .byAnyPackage("..controller..", "..service..");
    /** impl下的类,不能是interface */
    @ArchTest
    public static final ArchRule interfaces_must_not_be_placed_in_implementation_packages = noClasses()
            .that()
            .resideInAPackage("..impl..")
            .should()
            .beInterfaces();
    /** 接口类,类名不能以Interface结尾 */
    @ArchTest
    public static final ArchRule interfaces_should_not_have_names_ending_with_the_word_interface = noClasses()
            .that()
            .areInterfaces()
            .should()
            .haveNameMatching(".*Interface");
    /** service下的类,不能调用controller下的类 */
    @ArchTest
    public static final ArchRule services_should_not_access_controllers = noClasses()
            .that()
            .resideInAPackage("..service..")
            .should()
            .accessClassesThat()
            .resideInAPackage("..controller..");
    /** dao下的类,不能调用controller下的类 */
    @ArchTest
    public static final ArchRule controllers_should_not_access_dao = noClasses()
            .that()
            .resideInAPackage("..dao..")
            .should()
            .accessClassesThat()
            .resideInAnyPackage("..controller..");
    /** 不应该使用System.* */
    @ArchTest
    private final ArchRule NO_ACCESS_TO_STANDARD_STREAMS = NO_CLASSES_SHOULD_ACCESS_STANDARD_STREAMS;
    /** 不应该抛出Exception */
    @ArchTest
    private final ArchRule NO_GENERIC_EXCEPTIONS = NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS;
    /** 不应该使用java.util.logging来记录日志 */
    @ArchTest
    private final ArchRule NO_JAVA_UTIL_LOGGING = NO_CLASSES_SHOULD_USE_JAVA_UTIL_LOGGING;
}
    List-2中的代码中已经给出注释,自己可以在项目中运行看下结果。不过发现有个不好的地方是,archunit会扫描test下的类。     注:如果要忽略某个规则,那么加上@ArchIgnore就可以了,参考这里。

2.1 忽略某个规则

public class ArchitectureTest {

    // will run
    @ArchTest
    public static final ArchRule rule1 = classes().should()...     // won't run
    @ArchIgnore
    @ArchTest
    public static final ArchRule rule2 = classes().should()...
}

2.2 忽略多个类,即不让Archunit扫描多个类

一般出现在遗留系统中。

如图 图2.1

![图2.1](https://oscimg.oschina.net/oscnet/af8ed5e83e516a1da4caefbe86c7c6b09ac.jpg)

    比如我们想在Archunit扫描时,忽略DemoInterface和AnnotationDemo,那么在resources下建个"archunit_ignore_patterns.txt"的文件(这个文件名称是固定的,不能修改),在将要忽略的类路径放入其中,注意格式,如下图2.2所示,参考其官网。

图2.2

3.Demo

    新建一个interface,名为DemoInterface,之后运行List-2,结果如下图1所示,由于DemoInterface是interface,类名以Interface结尾(List-2中定义不能以Interface结尾),未以I开头(List-2中定义要以I开头):

图3.1  运行List-2后报错信息

图3.1 运行List-2后报错信息

4.官方的Archunit example

可以在Github上看Archunit的例子,Github地址: https://github.com/TNG/ArchUnit-Examples    

实际项目中,代码量较多,规范要做好,特别是人员流动是公司中很常见的。

```

转载-Archunit的使用的更多相关文章

  1. Crystal Clear Applied: The Seven Properties of Running an Agile Project (转载)

    作者Alistair Cockburn, Crystal Clear的7个成功要素,写得挺好. 敏捷方法的关注点,大家可以参考,太激动所以转载了. 原文:http://www.informit.com ...

  2. RTP与RTCP协议介绍(转载)

    RTSP发起/终结流媒体.RTP传输流媒体数据 .RTCP对RTP进行控制,同步.RTP中没有连接的概念,本身并不能为按序传输数据包提供可靠的保证,也不提供流量控制和拥塞控制,这些都由RTCP来负责完 ...

  3. 《Walking the callstack(转载)》

    本文转载自:https://www.codeproject.com/articles/11132/walking-the-callstack Download demo project with so ...

  4. [转载]MVVM模式原理分析及实践

    没有找到很好的MVVM模式介绍文章,简单找了一篇,分享一下.MVVM实现了UI\UE设计师(Expression Blend 4设计界面)和软件工程师的合理分工,在SilverLight.WPF.Wi ...

  5. [转载]:STM32为什么必须先配置时钟再配置GPIO

    转载来源 :http://blog.csdn.net/fushiqianxun/article/details/7926442 [原创]:我来添两句,就是很多同学(包括我)之前搞低端单片机,到了stm ...

  6. [转载]从MyEclipse到IntelliJ IDEA-让你摆脱鼠标,全键盘操作

    从MyEclipse转战到IntelliJ IDEA的经历 注转载址:http://blog.csdn.net/luoweifu/article/details/13985835 我一个朋友写了一篇“ ...

  7. TCP同步与异步,长连接与短连接【转载】

    原文地址:TCP同步与异步,长连接与短连接作者:1984346023 [转载说明:http://zjj1211.blog.51cto.com/1812544/373896   这是今天看到的一篇讲到T ...

  8. 在CentOS 7/6.5/6.4 中安装Java JDK 8(转载)

    转载在CentOS 7/6.5/6.4 中安装Java JDK 8 首先,在你的服务器上运行一下更新. yum update 然后,在您的系统上搜索,任何版本的已安装的JDK组件. rpm -qa | ...

  9. 用C#实现MD5的加密(转载)

    方法一 首先,先简单介绍一下MD5 MD5的全称是message-digest algorithm 5(信息-摘要算法,在90年代初由mit laboratory for computer scien ...

随机推荐

  1. LRU算法与增强

    概要本文的想法来自于本人学习MySQL时的一个知识点:MySQL Innodb引擎中对缓冲区的处理.虽然没有仔细研究其源码实现,但其设计仍然启发了我. 本文针对LRU存在的问题,思考一种增强算法来避免 ...

  2. 16个Spring注解,你知道的有几个?

    @Controller 标识一个该类是Spring MVC controller处理器,用来创建处理http请求的对象.   @RestController Spring4之后加入的注解,原来在@Co ...

  3. ansible部署Tomcat

    首先要准备的环境就是免密登录 这是要在ansible-playbook中所写的内容---- hosts: tomcat tasks:   - name: 关闭防火墙     service: name ...

  4. CCF-CSP题解 201903-3 损坏的RAID5

    先吐槽先吐槽!因为输入太大,需要用fgets,读n个字符或读到回车终止. char *fgets(char *str, int n, FILE *stream) 因为scanf模拟考试T了10+次.因 ...

  5. VS2019 开发Django(十一)------表单

    导航:VS2019开发Django系列 今天是中华人民共和国成立70周年的日子,普天同庆,看阅兵看得满腔热血,热泪盈眶,祖国都这么优秀了,我要更加努力才行啊! 这个Django系列的文章,没有很深入的 ...

  6. 约数之和(POJ1845 Sumdiv)

    最近应老延的要求再刷<算法进阶指南>(不得不说这本书不错)...这道题花费了较长时间~(当然也因为我太弱了)所以就写个比较易懂的题解啦~ 原题链接:POJ1845 翻译版题目(其实是AcW ...

  7. C# 模拟浏览器并自动操作

    本文主要讲解通过WebBrowser控件打开浏览页面,并操作页面元素实现自动搜索功能,仅供学习分享使用,如有不足之处,还请指正. 涉及知识点 WebBrowser:用于在WinForm窗体中,模拟浏览 ...

  8. Python面向对象-概念、类、实例

    OOP——Object Oriented Programming,面向对象编程,是一种程序设计思想.该思想将对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 区别于面向过程的程序设计即把计 ...

  9. JS---offset系列和scroll系列

    元素的样式属性是无法直接通过:对象.style.属性来获取(样式在style属性中设置)   offset系列: offsetLeft:距离左边位置的值 offsetTop:距离上面位置的值 offs ...

  10. gohook 一个支持运行时替换 golang 函数的库实现

    运行时替换函数对 golang 这类静态语言来说并不是件容易的事情,语言层面的不支持导致只能从机器码层面做些奇怪 hack,往往艰难,但如能成功,那挣脱牢笼带来的成就感,想想就让人兴奋. gohook ...