当前位置: 首页 > 知识库问答 >
问题:

使用 Spring 进行 Java Bean 方法约束验证不适用于构造函数

田琛
2023-03-14

我目前正在尝试使用HiberNate Validator实现一些方法约束验证。我已经定义

  1. 方法的参数约束
  2. 方法的返回值约束
  3. 构造函数的参数约束
  4. 构造函数的返回值约束

使用ExecutableValidator接口的手动验证(如Hibernate Validator文档中所述)非常适合1。-4.

与Spring的集成基本上是用@Validated注释bean。当我试图用@Validated在Spring容器中验证我的约束时,只有1。第二。,即方法的验证,工作,但不是为构造函数(3。第四。).

有什么想法,出了什么问题?

我创建了一个最小的工作示例:第一个测试用例是成功的,即使第二个测试用例失败了,因为在调用setter的时候抛出了ConstraintViolationException(实际上,异常也应该在一行之前抛出)。

我的客户bean,应进行验证(注意:setFirst stName()的参数有@NotNull注释):

@Validated
public class Customer {

  private String firstName;

  private String lastName;

  public Customer(@NotNull String firstName, @NotNull String lastName) {
      this.firstName = firstName;
      this.lastName = lastName;
  }

  public String getFirstName() {
      return firstName;
  }

  public void setFirstName(@NotNull String firstName) {
      this.firstName = firstName;
  }

  public String getLastName() {
      return lastName;
  }

  public void setLastName(String lastName) {
      this.lastName = lastName;
  }
}

所属配置:

@Configuration
@ComponentScan({ "com.example.demo" })
public class MethodValidationConfig {

  @Bean
  public MethodValidationPostProcessor methodValidationPostProcessor() {
      return new MethodValidationPostProcessor();
  }

  @Bean("customer")
  @Scope(BeanDefinition.SCOPE_PROTOTYPE)
  public Customer customer(String firstName, String lastName) {

      Customer customer = new Customer(firstName, lastName);
      return customer;
  }
}

然后是两个测试案例。如前所述,第一个不会抛出异常,即使它应该抛出异常。第二个抛出异常,但是在调用setter的时候,而不是之前。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { MethodValidationConfig.class }, loader = 
AnnotationConfigContextLoader.class)
public class DemoApplicationTests {

  @Autowired
  private ApplicationContext applicationContext;

  @Test
  public void callConstructorWithInvalidParameter(){

      Customer c = (Customer) applicationContext.getBean("customer", null, null);
  }

  @Test
  public void callSetterWithInvalidParameter(){

      Customer c = (Customer) applicationContext.getBean("customer", "John", "Doe");
      c.setFirstName(null);
  }

}

最后我的pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
    http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.0.7.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator-annotation-processor</artifactId>
            <version>6.0.7.Final</version>
        </dependency>
        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>javax.el-api</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>javax.el</artifactId>
            <version>2.2.6</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.2.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
    <packaging>jar</packaging>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
</project>

共有1个答案

韶亮
2023-03-14

Spring验证使用AOP。默认情况下,使用Spring AOP。Spring AOP是一个运行时AOP实现,它代理托管组件(又名beans)。

出于同样的原因,不能用spring AOP通知构造函数,因此验证不起作用。

对于更复杂的AOP,请考虑A

 类似资料:
  • 我希望对spring服务的参数使用java bean验证注释。考虑以下服务:

  • 每个人 因此,我有一个SpringBoot应用程序,它带有一个控制器,该控制器有几种方法,将以下POJO作为参数: 对于其中一个控制器endpoint,我想应用额外的验证逻辑,因此在我添加了以下内容: 是我想要应用的约束注释。 我的问题是,只有在中定义的检查成功通过时,才会调用此附加约束。如果为空,约束将被忽略,客户端将收到不完整的验证结果。我错过了什么?

  • 问题内容: 如何使用Hibernate验证程序来验证构造函数或方法中的参数?我希望在ValueObject创建之前进行验证,因此除非所有参数都有效,否则我可以引发异常而不创建对象。 基本上,我正在尝试使用注释,而不是尽可能执行以下操作: 我试过遵循这样的文档,虽然看起来似乎有效,但仍然会导致创建对象。 将注释添加到构造函数参数似乎无效 我如何创建对象: 验证器: 问题答案: 对于找到此帖子的其他任

  • 问题内容: 我有一个DummyResource类和一个DummyTarget文件,以及一个测试类TestDummyResource,如下所示,但是模拟对象仅在我在普通类中调用构造函数时才起作用,在匿名类中调用它时,它调用的是实际构造函数而不是使用模拟对象。 版本: powermock 1.4.12模拟1.9.0 junit 4.8.2 DummyTarget.java: DummyResource

  • 我定义了一个外键。为了检查它,我在具有外键的表中插入了错误的值。未打印任何错误,值已成功添加。我不知道我是否正在运行一些旧版本的sqlite3或类似的东西,我对这个领域是完全陌生的。 创建表ref(value 1 int, value 2,主键(value 1)); 为(value1 int、value3 int、主键(value3)、外键(value1)引用ref(value1))创建表; 插入