summaryrefslogtreecommitdiff
path: root/spring-context
diff options
context:
space:
mode:
authorEmmanuel Bourg <ebourg@apache.org>2019-01-01 11:22:29 +0100
committerEmmanuel Bourg <ebourg@apache.org>2019-01-01 11:22:29 +0100
commitd2188a36ffbb40643baa12f9a68494774552563f (patch)
treebe7118bd87b5b0960603ccda439d474261fbd69d /spring-context
parentcb53abe54064010cd788530c7a882ecebb88afcd (diff)
New upstream version 4.3.21
Diffstat (limited to 'spring-context')
-rw-r--r--spring-context/src/main/java/org/springframework/context/annotation/DependsOn.java8
-rw-r--r--spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java19
-rw-r--r--spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java170
-rw-r--r--spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java5
-rw-r--r--spring-context/src/test/java/org/springframework/tests/mock/jndi/ExpectedLookupTemplate.java27
-rw-r--r--spring-context/src/test/java/org/springframework/tests/mock/jndi/SimpleNamingContextBuilder.java14
-rw-r--r--spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationTests.java24
7 files changed, 237 insertions, 30 deletions
diff --git a/spring-context/src/main/java/org/springframework/context/annotation/DependsOn.java b/spring-context/src/main/java/org/springframework/context/annotation/DependsOn.java
index 121cec3a..48f3dc05 100644
--- a/spring-context/src/main/java/org/springframework/context/annotation/DependsOn.java
+++ b/spring-context/src/main/java/org/springframework/context/annotation/DependsOn.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 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.
@@ -28,6 +28,12 @@ import java.lang.annotation.Target;
* does not explicitly depend on another through properties or constructor arguments,
* but rather depends on the side effects of another bean's initialization.
*
+ * <p>A depends-on declaration can specify both an initialization-time dependency and,
+ * in the case of singleton beans only, a corresponding destruction-time dependency.
+ * Dependent beans that define a depends-on relationship with a given bean are destroyed
+ * first, prior to the given bean itself being destroyed. Thus, a depends-on declaration
+ * can also control shutdown order.
+ *
* <p>May be used on any class directly or indirectly annotated with
* {@link org.springframework.stereotype.Component} or on methods annotated
* with {@link Bean}.
diff --git a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java
index 42427f4c..473ba922 100644
--- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java
+++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java
@@ -171,8 +171,23 @@ public class MethodValidationInterceptor implements MethodInterceptor {
private boolean isFactoryBeanMetadataMethod(Method method) {
Class<?> clazz = method.getDeclaringClass();
- return ((clazz == FactoryBean.class || clazz == SmartFactoryBean.class) &&
- !method.getName().equals("getObject"));
+
+ // Call from interface-based proxy handle, allowing for an efficient check?
+ if (clazz.isInterface()) {
+ return ((clazz == FactoryBean.class || clazz == SmartFactoryBean.class) &&
+ !method.getName().equals("getObject"));
+ }
+
+ // Call from CGLIB proxy handle, potentially implementing a FactoryBean method?
+ Class<?> factoryBeanType = null;
+ if (SmartFactoryBean.class.isAssignableFrom(clazz)) {
+ factoryBeanType = SmartFactoryBean.class;
+ }
+ else if (FactoryBean.class.isAssignableFrom(clazz)) {
+ factoryBeanType = FactoryBean.class;
+ }
+ return (factoryBeanType != null && !method.getName().equals("getObject") &&
+ ClassUtils.hasMethod(factoryBeanType, method.getName(), method.getParameterTypes()));
}
/**
diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java
index dcf2f373..dd053d7b 100644
--- a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java
+++ b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java
@@ -544,6 +544,10 @@ public class ConfigurationClassPostProcessorTests {
beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
assertEquals(1, beanNames.length);
assertEquals("stringRepo", beanNames[0]);
+
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
}
@Test
@@ -558,6 +562,78 @@ public class ConfigurationClassPostProcessorTests {
beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
assertEquals(1, beanNames.length);
assertEquals("stringRepo", beanNames[0]);
+
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
+ }
+
+ @Test
+ public void genericsBasedInjectionWithEarlyGenericsMatchingAndRawFactoryMethod() {
+ beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawFactoryMethodRepositoryConfiguration.class));
+ new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
+
+ String[] beanNames = beanFactory.getBeanNamesForType(Repository.class);
+ assertTrue(ObjectUtils.containsElement(beanNames, "stringRepo"));
+
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
+ assertEquals(0, beanNames.length);
+
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
+ assertEquals(0, beanNames.length);
+ }
+
+ @Test
+ public void genericsBasedInjectionWithLateGenericsMatchingAndRawFactoryMethod() {
+ beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawFactoryMethodRepositoryConfiguration.class));
+ new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
+ beanFactory.preInstantiateSingletons();
+
+ String[] beanNames = beanFactory.getBeanNamesForType(Repository.class);
+ assertTrue(ObjectUtils.containsElement(beanNames, "stringRepo"));
+
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
+
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
+ }
+
+ @Test
+ public void genericsBasedInjectionWithEarlyGenericsMatchingAndRawInstance() {
+ beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawInstanceRepositoryConfiguration.class));
+ new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
+
+ String[] beanNames = beanFactory.getBeanNamesForType(Repository.class);
+ assertTrue(ObjectUtils.containsElement(beanNames, "stringRepo"));
+
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
+
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
+ }
+
+ @Test
+ public void genericsBasedInjectionWithLateGenericsMatchingAndRawInstance() {
+ beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawInstanceRepositoryConfiguration.class));
+ new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
+ beanFactory.preInstantiateSingletons();
+
+ String[] beanNames = beanFactory.getBeanNamesForType(Repository.class);
+ assertTrue(ObjectUtils.containsElement(beanNames, "stringRepo"));
+
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
+
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
}
@Test
@@ -577,6 +653,10 @@ public class ConfigurationClassPostProcessorTests {
assertEquals(1, beanNames.length);
assertEquals("stringRepo", beanNames[0]);
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
+
assertTrue(AopUtils.isCglibProxy(beanFactory.getBean("stringRepo")));
}
@@ -598,12 +678,16 @@ public class ConfigurationClassPostProcessorTests {
assertEquals(1, beanNames.length);
assertEquals("stringRepo", beanNames[0]);
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
+
assertTrue(AopUtils.isCglibProxy(beanFactory.getBean("stringRepo")));
}
@Test
public void genericsBasedInjectionWithLateGenericsMatchingOnCglibProxyAndRawFactoryMethod() {
- beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawRepositoryConfiguration.class));
+ beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawFactoryMethodRepositoryConfiguration.class));
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
autoProxyCreator.setProxyTargetClass(true);
@@ -619,6 +703,35 @@ public class ConfigurationClassPostProcessorTests {
assertEquals(1, beanNames.length);
assertEquals("stringRepo", beanNames[0]);
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
+
+ assertTrue(AopUtils.isCglibProxy(beanFactory.getBean("stringRepo")));
+ }
+
+ @Test
+ public void genericsBasedInjectionWithLateGenericsMatchingOnCglibProxyAndRawInstance() {
+ beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawInstanceRepositoryConfiguration.class));
+ new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
+ DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
+ autoProxyCreator.setProxyTargetClass(true);
+ autoProxyCreator.setBeanFactory(beanFactory);
+ beanFactory.addBeanPostProcessor(autoProxyCreator);
+ beanFactory.registerSingleton("traceInterceptor", new DefaultPointcutAdvisor(new SimpleTraceInterceptor()));
+ beanFactory.preInstantiateSingletons();
+
+ String[] beanNames = beanFactory.getBeanNamesForType(Repository.class);
+ assertTrue(ObjectUtils.containsElement(beanNames, "stringRepo"));
+
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
+
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
+
assertTrue(AopUtils.isCglibProxy(beanFactory.getBean("stringRepo")));
}
@@ -638,6 +751,10 @@ public class ConfigurationClassPostProcessorTests {
assertEquals(1, beanNames.length);
assertEquals("stringRepo", beanNames[0]);
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(RepositoryInterface.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
+
assertTrue(AopUtils.isJdkDynamicProxy(beanFactory.getBean("stringRepo")));
}
@@ -658,12 +775,16 @@ public class ConfigurationClassPostProcessorTests {
assertEquals(1, beanNames.length);
assertEquals("stringRepo", beanNames[0]);
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(RepositoryInterface.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
+
assertTrue(AopUtils.isJdkDynamicProxy(beanFactory.getBean("stringRepo")));
}
@Test
public void genericsBasedInjectionWithLateGenericsMatchingOnJdkProxyAndRawFactoryMethod() {
- beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawRepositoryConfiguration.class));
+ beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawFactoryMethodRepositoryConfiguration.class));
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
autoProxyCreator.setBeanFactory(beanFactory);
@@ -678,6 +799,34 @@ public class ConfigurationClassPostProcessorTests {
assertEquals(1, beanNames.length);
assertEquals("stringRepo", beanNames[0]);
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(RepositoryInterface.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
+
+ assertTrue(AopUtils.isJdkDynamicProxy(beanFactory.getBean("stringRepo")));
+ }
+
+ @Test
+ public void genericsBasedInjectionWithLateGenericsMatchingOnJdkProxyAndRawInstance() {
+ beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawInstanceRepositoryConfiguration.class));
+ new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
+ DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
+ autoProxyCreator.setBeanFactory(beanFactory);
+ beanFactory.addBeanPostProcessor(autoProxyCreator);
+ beanFactory.registerSingleton("traceInterceptor", new DefaultPointcutAdvisor(new SimpleTraceInterceptor()));
+ beanFactory.preInstantiateSingletons();
+
+ String[] beanNames = beanFactory.getBeanNamesForType(RepositoryInterface.class);
+ assertTrue(ObjectUtils.containsElement(beanNames, "stringRepo"));
+
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(RepositoryInterface.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
+
+ beanNames = beanFactory.getBeanNamesForType(ResolvableType.forClassWithGenerics(RepositoryInterface.class, String.class));
+ assertEquals(1, beanNames.length);
+ assertEquals("stringRepo", beanNames[0]);
+
assertTrue(AopUtils.isJdkDynamicProxy(beanFactory.getBean("stringRepo")));
}
@@ -980,7 +1129,7 @@ public class ConfigurationClassPostProcessorTests {
}
@Configuration
- public static class RawRepositoryConfiguration {
+ public static class RawFactoryMethodRepositoryConfiguration {
@Bean
public Repository stringRepo() {
@@ -994,6 +1143,21 @@ public class ConfigurationClassPostProcessorTests {
}
@Configuration
+ public static class RawInstanceRepositoryConfiguration {
+
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ @Bean
+ public Repository<String> stringRepo() {
+ return new Repository() {
+ @Override
+ public String toString() {
+ return "Repository<String>";
+ }
+ };
+ }
+ }
+
+ @Configuration
public static class ScopedRepositoryConfiguration {
@Bean
diff --git a/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java b/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java
index ed5b11fc..9eb5aefe 100644
--- a/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java
+++ b/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java
@@ -161,7 +161,7 @@ public class EnableAsyncTests {
Object bean = ctx.getBean(CustomAsyncBean.class);
assertTrue(AopUtils.isAopProxy(bean));
boolean isAsyncAdvised = false;
- for (Advisor advisor : ((Advised)bean).getAdvisors()) {
+ for (Advisor advisor : ((Advised) bean).getAdvisors()) {
if (advisor instanceof AsyncAnnotationAdvisor) {
isAsyncAdvised = true;
break;
@@ -365,7 +365,8 @@ public class EnableAsyncTests {
@EnableAsync
static class AsyncConfigWithMockito {
- @Bean @Lazy
+ @Bean
+ @Lazy
public AsyncBean asyncBean() {
return Mockito.mock(AsyncBean.class);
}
diff --git a/spring-context/src/test/java/org/springframework/tests/mock/jndi/ExpectedLookupTemplate.java b/spring-context/src/test/java/org/springframework/tests/mock/jndi/ExpectedLookupTemplate.java
index 8cc22aab..00c3d24c 100644
--- a/spring-context/src/test/java/org/springframework/tests/mock/jndi/ExpectedLookupTemplate.java
+++ b/spring-context/src/test/java/org/springframework/tests/mock/jndi/ExpectedLookupTemplate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 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,28 +23,29 @@ import javax.naming.NamingException;
import org.springframework.jndi.JndiTemplate;
/**
- * Simple extension of the JndiTemplate class that always returns
- * a given object. Very useful for testing. Effectively a mock object.
+ * Simple extension of the JndiTemplate class that always returns a given object.
+ *
+ * <p>Very useful for testing. Effectively a mock object.
*
* @author Rod Johnson
* @author Juergen Hoeller
*/
public class ExpectedLookupTemplate extends JndiTemplate {
- private final Map<String, Object> jndiObjects = new ConcurrentHashMap<String, Object>();
+ private final Map<String, Object> jndiObjects = new ConcurrentHashMap<String, Object>(16);
/**
- * Construct a new JndiTemplate that will always return given objects
- * for given names. To be populated through {@code addObject} calls.
+ * Construct a new JndiTemplate that will always return given objects for
+ * given names. To be populated through {@code addObject} calls.
* @see #addObject(String, Object)
*/
public ExpectedLookupTemplate() {
}
/**
- * Construct a new JndiTemplate that will always return the
- * given object, but honour only requests for the given name.
+ * Construct a new JndiTemplate that will always return the given object,
+ * but honour only requests for the given name.
* @param name the name the client is expected to look up
* @param object the object that will be returned
*/
@@ -54,8 +55,7 @@ public class ExpectedLookupTemplate extends JndiTemplate {
/**
- * Add the given object to the list of JNDI objects that this
- * template will expose.
+ * Add the given object to the list of JNDI objects that this template will expose.
* @param name the name the client is expected to look up
* @param object the object that will be returned
*/
@@ -63,11 +63,10 @@ public class ExpectedLookupTemplate extends JndiTemplate {
this.jndiObjects.put(name, object);
}
-
/**
- * If the name is the expected name specified in the constructor,
- * return the object provided in the constructor. If the name is
- * unexpected, a respective NamingException gets thrown.
+ * If the name is the expected name specified in the constructor, return the
+ * object provided in the constructor. If the name is unexpected, a
+ * respective NamingException gets thrown.
*/
@Override
public Object lookup(String name) throws NamingException {
diff --git a/spring-context/src/test/java/org/springframework/tests/mock/jndi/SimpleNamingContextBuilder.java b/spring-context/src/test/java/org/springframework/tests/mock/jndi/SimpleNamingContextBuilder.java
index 1ae3b78d..b4fe464e 100644
--- a/spring-context/src/test/java/org/springframework/tests/mock/jndi/SimpleNamingContextBuilder.java
+++ b/spring-context/src/test/java/org/springframework/tests/mock/jndi/SimpleNamingContextBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 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.
@@ -26,6 +26,7 @@ import javax.naming.spi.NamingManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
@@ -35,13 +36,14 @@ import org.springframework.util.ClassUtils;
* configure JNDI appropriately, so that {@code new InitialContext()}
* will expose the required objects. Also usable for standalone applications,
* e.g. for binding a JDBC DataSource to a well-known JNDI location, to be
- * able to use traditional J2EE data access code outside of a J2EE container.
+ * able to use traditional Java EE data access code outside of a Java EE
+ * container.
*
* <p>There are various choices for DataSource implementations:
* <ul>
* <li>{@code SingleConnectionDataSource} (using the same Connection for all getConnection calls)
* <li>{@code DriverManagerDataSource} (creating a new Connection on each getConnection call)
- * <li>Apache's Jakarta Commons DBCP offers {@code org.apache.commons.dbcp.BasicDataSource} (a real pool)
+ * <li>Apache's Commons DBCP offers {@code org.apache.commons.dbcp.BasicDataSource} (a real pool)
* </ul>
*
* <p>Typical usage in bootstrap code:
@@ -98,7 +100,7 @@ public class SimpleNamingContextBuilder implements InitialContextFactoryBuilder
/**
* If no SimpleNamingContextBuilder is already configuring JNDI,
- * create and activate one. Otherwise take the existing activate
+ * create and activate one. Otherwise take the existing activated
* SimpleNamingContextBuilder, clear it and return it.
* <p>This is mainly intended for test suites that want to
* reinitialize JNDI bindings from scratch repeatedly.
@@ -137,12 +139,10 @@ public class SimpleNamingContextBuilder implements InitialContextFactoryBuilder
logger.info("Activating simple JNDI environment");
synchronized (initializationLock) {
if (!initialized) {
- if (NamingManager.hasInitialContextFactoryBuilder()) {
- throw new IllegalStateException(
+ Assert.state(!NamingManager.hasInitialContextFactoryBuilder(),
"Cannot activate SimpleNamingContextBuilder: there is already a JNDI provider registered. " +
"Note that JNDI is a JVM-wide service, shared at the JVM system class loader level, " +
"with no reset option. As a consequence, a JNDI provider must only be registered once per JVM.");
- }
NamingManager.setInitialContextFactoryBuilder(this);
initialized = true;
}
diff --git a/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationTests.java b/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationTests.java
index 63746bbb..dbd8b5cd 100644
--- a/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationTests.java
+++ b/spring-context/src/test/java/org/springframework/validation/beanvalidation/MethodValidationTests.java
@@ -123,7 +123,16 @@ public class MethodValidationTests {
@Test
public void testLazyValidatorForMethodValidation() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
- LazyMethodValidationConfig.class, CustomValidatorBean.class, MyValidBean.class, MyValidFactoryBean.class);
+ LazyMethodValidationConfig.class, CustomValidatorBean.class,
+ MyValidBean.class, MyValidFactoryBean.class);
+ ctx.getBeansOfType(MyValidInterface.class).values().forEach(bean -> bean.myValidMethod("value", 5));
+ }
+
+ @Test
+ public void testLazyValidatorForMethodValidationWithProxyTargetClass() {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
+ LazyMethodValidationConfigWithProxyTargetClass.class, CustomValidatorBean.class,
+ MyValidBean.class, MyValidFactoryBean.class);
ctx.getBeansOfType(MyValidInterface.class).values().forEach(bean -> bean.myValidMethod("value", 5));
}
@@ -223,4 +232,17 @@ public class MethodValidationTests {
}
}
+
+ @Configuration
+ public static class LazyMethodValidationConfigWithProxyTargetClass {
+
+ @Bean
+ public static MethodValidationPostProcessor methodValidationPostProcessor(@Lazy Validator validator) {
+ MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();
+ postProcessor.setValidator(validator);
+ postProcessor.setProxyTargetClass(true);
+ return postProcessor;
+ }
+ }
+
}