如何用ArchUnit禁止Spring Bean中修改实例变量状态?
问题描述
我有如下形式的Spring Bean:
@Service public class HotelsService { public List<Hotel> fetchAllHotels() { return dummyHotelsList(); } }
我希望阻止开发者在此类Bean中创建实例变量并在方法内修改其状态(如下是不希望出现的代码示例):
@Service public class HotelsService { private int someInteger; public List<Hotel> fetchAllHotels() { this.someInteger=1; // just for example return dummyHotelsList(); } }
我允许存在实例变量并对其进行读取,但禁止写入操作。不想通过代码评审流程来管控此问题,请问是否有简便的ArchUnit实现方案?
ArchUnit 实现方案
先引入依赖
先在项目中添加ArchUnit的JUnit5依赖(以Maven为例):
<dependency> <groupId>com.tngtech.archunit</groupId> <artifactId>archunit-junit5</artifactId> <version>1.2.1</version> <scope>test</scope> </dependency>
编写测试规则
创建一个测试类,用ArchUnit定义规则就能实现需求:
import com.tngtech.archunit.core.domain.JavaClasses; import com.tngtech.archunit.core.importer.ClassFileImporter; import com.tngtech.archunit.lang.ArchRule; import com.tngtech.archunit.lang.syntax.ArchRuleDefinition; import org.junit.jupiter.api.Test; import org.springframework.stereotype.Service; public class ServiceBeanRulesTest { @Test void serviceBeansShouldNotModifyInstanceVariables() { // 替换为你的项目基础包路径 JavaClasses classes = new ClassFileImporter().importPackages("com.yourcompany.yourproject"); ArchRule rule = ArchRuleDefinition.classes() .that().areAnnotatedWith(Service.class) .should().notHaveMethodsThatModifyTheirDeclaringClassFields(); rule.check(classes); } }
规则作用说明
- 该规则会扫描指定包下所有标注了
@Service的类 - 严格禁止这些类中的方法对自身的实例变量进行赋值修改
- 完全匹配你的需求:允许读取实例变量,但写入操作直接被拦截
扩展支持final字段
如果需要允许final类型的实例变量(这类变量仅能在初始化时赋值,后续无法修改),可以调整规则排除对final字段的初始化操作:
ArchRule rule = ArchRuleDefinition.classes() .that().areAnnotatedWith(Service.class) .should().notHaveMethodsThatModifyNonFinalDeclaringClassFields();
使用方式
将这个测试加入项目的单元测试套件,每次构建时都会自动执行。一旦有开发者写出修改实例变量的代码,测试会直接失败,无需代码评审就能及时拦截不符合规范的写法。
内容的提问来源于stack exchange,提问作者Arun
相关产品推荐
相关产品推荐

