繁体   English   中英

Spring Boot @Autowired - checkstyle / pmd / spotbugs 规则以警告非接口使用

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM