From 77887ef739d3cb6a85bee6cc1027fc200bea3698 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 13 Sep 2018 20:24:27 +0200 Subject: [PATCH] BeanValidationPostProcessor validates singleton target behind proxy Issue: SPR-17273 --- .../BeanValidationPostProcessor.java | 10 ++++++-- .../BeanValidationPostProcessorTests.java | 23 ++++++++++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/validation/beanvalidation/BeanValidationPostProcessor.java b/spring-context/src/main/java/org/springframework/validation/beanvalidation/BeanValidationPostProcessor.java index 1c7a8a9d549..14f989af276 100644 --- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/BeanValidationPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/BeanValidationPostProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; +import org.springframework.aop.framework.AopProxyUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanInitializationException; import org.springframework.beans.factory.InitializingBean; @@ -107,7 +108,12 @@ public class BeanValidationPostProcessor implements BeanPostProcessor, Initializ */ protected void doValidate(Object bean) { Assert.state(this.validator != null, "No Validator set"); - Set> result = this.validator.validate(bean); + Object objectToValidate = AopProxyUtils.getSingletonTarget(bean); + if (objectToValidate == null) { + objectToValidate = bean; + } + Set> result = this.validator.validate(objectToValidate); + if (!result.isEmpty()) { StringBuilder sb = new StringBuilder("Bean state is invalid: "); for (Iterator> it = result.iterator(); it.hasNext();) { diff --git a/spring-context/src/test/java/org/springframework/validation/beanvalidation/BeanValidationPostProcessorTests.java b/spring-context/src/test/java/org/springframework/validation/beanvalidation/BeanValidationPostProcessorTests.java index 3cadae83d5f..10e752a016c 100644 --- a/spring-context/src/test/java/org/springframework/validation/beanvalidation/BeanValidationPostProcessorTests.java +++ b/spring-context/src/test/java/org/springframework/validation/beanvalidation/BeanValidationPostProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,10 +22,13 @@ import javax.validation.constraints.Size; import org.junit.Test; +import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor; import org.springframework.context.support.GenericApplicationContext; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.AsyncAnnotationAdvisor; import org.springframework.tests.sample.beans.TestBean; import static org.junit.Assert.*; @@ -76,6 +79,20 @@ public class BeanValidationPostProcessorTests { ac.close(); } + @Test + public void testNotNullConstraintAfterInitializationWithProxy() { + GenericApplicationContext ac = new GenericApplicationContext(); + RootBeanDefinition bvpp = new RootBeanDefinition(BeanValidationPostProcessor.class); + bvpp.getPropertyValues().add("afterInitialization", true); + ac.registerBeanDefinition("bvpp", bvpp); + ac.registerBeanDefinition("capp", new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class)); + ac.registerBeanDefinition("bean", new RootBeanDefinition(AfterInitConstraintBean.class)); + ac.registerBeanDefinition("autoProxyCreator", new RootBeanDefinition(DefaultAdvisorAutoProxyCreator.class)); + ac.registerBeanDefinition("asyncAdvisor", new RootBeanDefinition(AsyncAnnotationAdvisor.class)); + ac.refresh(); + ac.close(); + } + @Test public void testSizeConstraint() { GenericApplicationContext ac = new GenericApplicationContext(); @@ -156,6 +173,10 @@ public class BeanValidationPostProcessorTests { public void init() { this.testBean = new TestBean(); } + + @Async + void asyncMethod() { + } } }