[英]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.