[英]Spring Boot @Autowired - checkstyle / pmd / spotbugs rule to warn on non-interface usage
最近在 Spring Boot 应用程序中被Spring CGLib 与 JDK 动态代理问题所困扰(在 Mac 上运行时似乎使用 CGLib,而在 Linux 上运行时使用 JDK 动态代理的同一个应用程序)。
我正在寻找一个 linter 工具配置/插件(PMD、Checkstyle、Spotbugs 等),它可以识别 @Autowired 注释字段/参数的使用位置,并且自动装配的类是用类实例而不是接口定义的。
例如:
public interface MyService {
}
public class MyServiceImpl implements MyService {
}
@RestController
public class MyController {
@Autowired
private MyServiceImpl serviceImpl; // this should raise a warning in a linter as
// class is being used for injection type
@Autowired
private MyService service; // this should not raise a warning, as interface
// is used for type
}
我认为这不可能通过 PMD、Checkstyle、Spotbugs 等进行检查。但是有一个解决方案可以检查这一点。 ArchUnit提供编写自定义规则,可以为此编写自定义规则。 假设您使用 JUnit5 或 JUnit4 进行测试,您可以执行以下操作 -
@ArchTest
public static final ArchRule archRule = noFields()
.that()
.areAnnotatedWith(Autowired.class)
.should()
.haveNameEndingWith("Impl");
这可以合并到您的测试中,您必须阅读 arch 单元的文档并在您的工作环境中进行设置,它非常容易集成。 您可以为设置器或方法创建类似的规则-
@ArchTest
public static final ArchRule archRule1 = noMethods()
.that()
.areAnnotatedWith(Autowired.class)
.should()
.haveRawParameterTypes(MyServiceImpl.class, MyDaoImpl.class);
当您将其集成到您的代码库中时,您可以为自己创建自定义规则。 将 ArchUnit 用于 spring 项目通常是一个好主意,它们还具有可在项目中使用的预配置模板。 希望这可以帮助。
除了上面@VyomYdv 的回答之外,我偶然发现了这个 github 问题的春季: https ://github.com/spring-projects/spring-boot/issues/8277
本质上,使用@Validated
和@ConfigurationProperties
注释并且还实现接口的bean 将成为运行时JDK 代理实例的候选对象,并且您不能自动装配类实例,您必须作为接口自动装配。
所以修改YyomYdv的规则如下:
public static final ArchRule AUTOWIRE_PROXY_RULE = noFields()
.that()
.areAnnotatedWith(Autowired.class)
.should()
.haveRawType(new DescribedPredicate<>("that does not autowire an interface") {
@Override
public boolean apply(final JavaClass input) {
return !input.isInterface();
}
})
.andShould().haveRawType(new DescribedPredicate<>("class is not a JDK proxy candidate") {
@Override
public boolean apply(final JavaClass input) {
return !input.getAllRawInterfaces().isEmpty()
&& input.getPackageName().startsWith("com.mypackage")
&& input.isAnnotatedWith(Validated.class)
&& input.isAnnotatedWith(ConfigurationProperties.class);
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.