You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用ArchUnit检查禁止直接调用Spring Bean创建方法?

问题:通过ArchUnit禁止直接调用@Bean标注的方法

Spring支持通过标注@Bean的方法创建Bean,示例代码如下:

@Bean
public DataSource springBatchDataSource() {
    SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
    // 省略其余初始化代码
    return dataSource;
}

该方法定义了名为springBatchDataSource的单例Bean,正常应通过@Autowired注入使用:

// 正确用法
@Autowired
DataSource ds;

但团队里的初级同事常会错误地直接调用该方法创建对象:

// 错误用法
DataSource ds = springBatchDataSource();

这种做法会生成多个实例(而非预期的单例Bean),引发严重的应用问题。因此希望添加ArchUnit检查来禁止这类调用。目前找到了callMethodWhere方法和areAnnotatedWith(Bean.class)断言,但不知道如何组合使用,请问代码片段中的???应替换为什么?

@ArchTest
void checkNoCallToBeanCreators(JavaClasses classes) {

    ArchRule rule = noClasses()
        .should().callMethodWhere(???.areAnnotatedWith(Bean.class));

    rule.check(classes);
}

或者有没有更优雅直接的实现方式?


解决方案

1. 填充???的正确写法

你需要用target()来指代被调用的目标方法,所以???处应替换为target(),完整代码如下:

@ArchTest
void checkNoCallToBeanCreators(JavaClasses classes) {
    ArchRule rule = noClasses()
        .should().callMethodWhere(target().areAnnotatedWith(Bean.class));

    rule.check(classes);
}

这段规则会扫描所有类,禁止它们调用任何被@Bean注解标注的方法。

2. 更严谨的优化写法

考虑到Spring允许@Configuration类内部调用@Bean方法来复用Bean实例(Spring会自动处理这类调用,确保返回单例),可以优化规则,只禁止外部类的非法调用:

@ArchTest
void checkNoExternalCallToBeanCreators(JavaClasses classes) {
    ArchRule rule = noClasses()
        .that().areNotAnnotatedWith(Configuration.class)
        .should().callMethodWhere(target().areAnnotatedWith(Bean.class));

    rule.check(classes);
}

3. 语义更清晰的等价写法

你也可以使用methods()语法来定义规则,语义更直观,可读性更强:

@ArchTest
void checkNoCallToBeanMethods(JavaClasses classes) {
    ArchRule rule = noClasses()
        .should().call(methods().that().areAnnotatedWith(Bean.class));

    rule.check(classes);
}

这段代码和第一种写法效果完全一致,但表达更直接。


内容的提问来源于stack exchange,提问作者mmo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 19:45:44