Browse Source

Make use of bean definition overriding more visible

This commit makes the use of bean definition overriding more visible and
prepare for a deprecation of the feature in the next major release.

As of this commit, use of bean definition overriding logs at INFO level.
The previous log level can be restored by setting the
allowBeanDefinitionOverriding flag explicitly on the BeanFactory (or
via the related ApplicationContext).

A number of tests that are using bean overriding on purpose have been
updated to set this flag, which will make them easier to find once we
actually deprecate the feature.

Closes gh-31288
pull/32568/head
Stéphane Nicoll 2 years ago
parent
commit
7a74e45946
  1. 16
      framework-docs/modules/ROOT/pages/core/beans/definition.adoc
  2. 64
      spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
  3. 6
      spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java
  4. 46
      spring-beans/src/test/java/org/springframework/beans/factory/annotation/LookupAnnotationTests.java
  5. 3
      spring-beans/src/test/java/org/springframework/beans/factory/xml/DuplicateBeanIdTests.java
  6. 1
      spring-beans/src/test/java/org/springframework/beans/factory/xml/NestedBeansElementTests.java
  7. 46
      spring-context-support/src/test/java/org/springframework/cache/jcache/config/JCacheCustomInterceptorTests.java
  8. 39
      spring-context/src/test/java/org/springframework/cache/config/CustomInterceptorTests.java
  9. 5
      spring-context/src/test/java/org/springframework/context/annotation/BeanMethodPolymorphismTests.java
  10. 1
      spring-context/src/test/java/org/springframework/context/annotation/ClassPathBeanDefinitionScannerTests.java
  11. 8
      spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java
  12. 5
      spring-context/src/test/java/org/springframework/context/annotation/EnableAspectJAutoProxyTests.java
  13. 8
      spring-context/src/test/java/org/springframework/context/annotation/NestedConfigurationClassTests.java
  14. 1
      spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportAnnotationDetectionTests.java
  15. 2
      spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportTests.java
  16. 2
      spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java
  17. 4
      spring-test/src/test/java/org/springframework/test/context/junit4/ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests.java

16
framework-docs/modules/ROOT/pages/core/beans/definition.adoc

@ -73,7 +73,23 @@ runtime (concurrently with live access to the factory) is not officially support
lead to concurrent access exceptions, inconsistent state in the bean container, or both. lead to concurrent access exceptions, inconsistent state in the bean container, or both.
==== ====
[[beans-definition-overriding]]
== Overriding Beans
Bean overriding is happening when a bean is registered using an identifier that is
already allocated. While bean overriding is possible, it makes the configuration harder
to read and this feature will be deprecated in a future release.
To disable bean overriding altogether, you can set the `allowBeanDefinitionOverriding`
to `false` on the `ApplicationContext` before it is refreshed. In such setup, an
exception is thrown if bean overriding is used.
By default, the container logs every bean overriding at `INFO` level so that you can
adapt your configuration accordingly. While not recommended, you can silence those logs
by setting the `allowBeanDefinitionOverriding` flag to `true`.
NOTE: We acknowledge that overriding beans in a test is convenient, and there is
explicit support for this. For more details please refer to xref:testing/annotations/integration-spring/annotation-beanoverriding.adoc[this section].
[[beans-beanname]] [[beans-beanname]]
== Naming Beans == Naming Beans

64
spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java

@ -152,7 +152,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
private String serializationId; private String serializationId;
/** Whether to allow re-registration of a different definition with the same name. */ /** Whether to allow re-registration of a different definition with the same name. */
private boolean allowBeanDefinitionOverriding = true; @Nullable
private Boolean allowBeanDefinitionOverriding;
/** Whether to allow eager class loading even for lazy-init beans. */ /** Whether to allow eager class loading even for lazy-init beans. */
private boolean allowEagerClassLoading = true; private boolean allowEagerClassLoading = true;
@ -259,7 +260,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
* @since 4.1.2 * @since 4.1.2
*/ */
public boolean isAllowBeanDefinitionOverriding() { public boolean isAllowBeanDefinitionOverriding() {
return this.allowBeanDefinitionOverriding; return !Boolean.FALSE.equals(this.allowBeanDefinitionOverriding);
} }
/** /**
@ -1142,27 +1143,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (!isBeanDefinitionOverridable(beanName)) { if (!isBeanDefinitionOverridable(beanName)) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
} }
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else { else {
if (logger.isTraceEnabled()) { logBeanDefinitionOverriding(beanName, beanDefinition, existingDefinition);
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
} }
this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionMap.put(beanName, beanDefinition);
} }
@ -1217,6 +1199,44 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
} }
} }
private void logBeanDefinitionOverriding(String beanName, BeanDefinition beanDefinition,
BeanDefinition existingDefinition) {
boolean explicitBeanOverride = (this.allowBeanDefinitionOverriding != null);
if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (explicitBeanOverride && logger.isInfoEnabled()) {
logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (explicitBeanOverride && logger.isInfoEnabled()) {
logger.info("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
}
@Override @Override
public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
Assert.hasText(beanName, "'beanName' must not be empty"); Assert.hasText(beanName, "'beanName' must not be empty");

6
spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java

@ -840,6 +840,7 @@ class DefaultListableBeanFactoryTests {
@Test @Test
void aliasCircle() { void aliasCircle() {
lbf.setAllowBeanDefinitionOverriding(true);
lbf.registerAlias("test", "test2"); lbf.registerAlias("test", "test2");
lbf.registerAlias("test2", "test3"); lbf.registerAlias("test2", "test3");
@ -867,6 +868,7 @@ class DefaultListableBeanFactoryTests {
@Test @Test
void beanDefinitionOverriding() { void beanDefinitionOverriding() {
lbf.setAllowBeanDefinitionOverriding(true);
lbf.registerBeanDefinition("test", new RootBeanDefinition(TestBean.class)); lbf.registerBeanDefinition("test", new RootBeanDefinition(TestBean.class));
lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class)); lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class));
lbf.registerAlias("otherTest", "test2"); lbf.registerAlias("otherTest", "test2");
@ -906,6 +908,7 @@ class DefaultListableBeanFactoryTests {
@Test @Test
void beanDefinitionOverridingWithAlias() { void beanDefinitionOverridingWithAlias() {
lbf.setAllowBeanDefinitionOverriding(true);
lbf.registerBeanDefinition("test", new RootBeanDefinition(TestBean.class)); lbf.registerBeanDefinition("test", new RootBeanDefinition(TestBean.class));
lbf.registerAlias("test", "testAlias"); lbf.registerAlias("test", "testAlias");
lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class)); lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class));
@ -917,6 +920,7 @@ class DefaultListableBeanFactoryTests {
@Test @Test
void beanDefinitionOverridingWithConstructorArgumentMismatch() { void beanDefinitionOverridingWithConstructorArgumentMismatch() {
lbf.setAllowBeanDefinitionOverriding(true);
RootBeanDefinition bd1 = new RootBeanDefinition(NestedTestBean.class); RootBeanDefinition bd1 = new RootBeanDefinition(NestedTestBean.class);
bd1.getConstructorArgumentValues().addIndexedArgumentValue(1, "value1"); bd1.getConstructorArgumentValues().addIndexedArgumentValue(1, "value1");
lbf.registerBeanDefinition("test", bd1); lbf.registerBeanDefinition("test", bd1);
@ -1196,6 +1200,7 @@ class DefaultListableBeanFactoryTests {
@Test @Test
void reregisterBeanDefinition() { void reregisterBeanDefinition() {
lbf.setAllowBeanDefinitionOverriding(true);
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class); RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
bd1.setScope(BeanDefinition.SCOPE_PROTOTYPE); bd1.setScope(BeanDefinition.SCOPE_PROTOTYPE);
lbf.registerBeanDefinition("testBean", bd1); lbf.registerBeanDefinition("testBean", bd1);
@ -1306,6 +1311,7 @@ class DefaultListableBeanFactoryTests {
@Test @Test
void withOverloadedSetters() { void withOverloadedSetters() {
lbf.setAllowBeanDefinitionOverriding(true);
RootBeanDefinition rbd = new RootBeanDefinition(SetterOverload.class); RootBeanDefinition rbd = new RootBeanDefinition(SetterOverload.class);
rbd.getPropertyValues().add("object", "a String"); rbd.getPropertyValues().add("object", "a String");
lbf.registerBeanDefinition("overloaded", rbd); lbf.registerBeanDefinition("overloaded", rbd);

46
spring-beans/src/test/java/org/springframework/beans/factory/annotation/LookupAnnotationTests.java

@ -16,7 +16,6 @@
package org.springframework.beans.factory.annotation; package org.springframework.beans.factory.annotation;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
@ -33,25 +32,9 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
*/ */
class LookupAnnotationTests { class LookupAnnotationTests {
private DefaultListableBeanFactory beanFactory;
@BeforeEach
void setup() {
beanFactory = new DefaultListableBeanFactory();
AutowiredAnnotationBeanPostProcessor aabpp = new AutowiredAnnotationBeanPostProcessor();
aabpp.setBeanFactory(beanFactory);
beanFactory.addBeanPostProcessor(aabpp);
beanFactory.registerBeanDefinition("abstractBean", new RootBeanDefinition(AbstractBean.class));
beanFactory.registerBeanDefinition("beanConsumer", new RootBeanDefinition(BeanConsumer.class));
RootBeanDefinition tbd = new RootBeanDefinition(TestBean.class);
tbd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
beanFactory.registerBeanDefinition("testBean", tbd);
}
@Test @Test
void testWithoutConstructorArg() { void testWithoutConstructorArg() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean"); AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean");
Object expected = bean.get(); Object expected = bean.get();
assertThat(expected.getClass()).isEqualTo(TestBean.class); assertThat(expected.getClass()).isEqualTo(TestBean.class);
@ -60,6 +43,7 @@ class LookupAnnotationTests {
@Test @Test
void testWithOverloadedArg() { void testWithOverloadedArg() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean"); AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean");
TestBean expected = bean.get("haha"); TestBean expected = bean.get("haha");
assertThat(expected.getClass()).isEqualTo(TestBean.class); assertThat(expected.getClass()).isEqualTo(TestBean.class);
@ -69,6 +53,7 @@ class LookupAnnotationTests {
@Test @Test
void testWithOneConstructorArg() { void testWithOneConstructorArg() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean"); AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean");
TestBean expected = bean.getOneArgument("haha"); TestBean expected = bean.getOneArgument("haha");
assertThat(expected.getClass()).isEqualTo(TestBean.class); assertThat(expected.getClass()).isEqualTo(TestBean.class);
@ -78,6 +63,7 @@ class LookupAnnotationTests {
@Test @Test
void testWithTwoConstructorArg() { void testWithTwoConstructorArg() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean"); AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean");
TestBean expected = bean.getTwoArguments("haha", 72); TestBean expected = bean.getTwoArguments("haha", 72);
assertThat(expected.getClass()).isEqualTo(TestBean.class); assertThat(expected.getClass()).isEqualTo(TestBean.class);
@ -88,6 +74,7 @@ class LookupAnnotationTests {
@Test @Test
void testWithThreeArgsShouldFail() { void testWithThreeArgsShouldFail() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean"); AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean");
assertThatExceptionOfType(AbstractMethodError.class).as("TestBean has no three arg constructor").isThrownBy(() -> assertThatExceptionOfType(AbstractMethodError.class).as("TestBean has no three arg constructor").isThrownBy(() ->
bean.getThreeArguments("name", 1, 2)); bean.getThreeArguments("name", 1, 2));
@ -96,6 +83,7 @@ class LookupAnnotationTests {
@Test @Test
void testWithEarlyInjection() { void testWithEarlyInjection() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
AbstractBean bean = beanFactory.getBean("beanConsumer", BeanConsumer.class).abstractBean; AbstractBean bean = beanFactory.getBean("beanConsumer", BeanConsumer.class).abstractBean;
Object expected = bean.get(); Object expected = bean.get();
assertThat(expected.getClass()).isEqualTo(TestBean.class); assertThat(expected.getClass()).isEqualTo(TestBean.class);
@ -106,7 +94,7 @@ class LookupAnnotationTests {
public void testWithNullBean() { public void testWithNullBean() {
RootBeanDefinition tbd = new RootBeanDefinition(TestBean.class, () -> null); RootBeanDefinition tbd = new RootBeanDefinition(TestBean.class, () -> null);
tbd.setScope(BeanDefinition.SCOPE_PROTOTYPE); tbd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
beanFactory.registerBeanDefinition("testBean", tbd); DefaultListableBeanFactory beanFactory = configureBeanFactory(tbd);
AbstractBean bean = beanFactory.getBean("beanConsumer", BeanConsumer.class).abstractBean; AbstractBean bean = beanFactory.getBean("beanConsumer", BeanConsumer.class).abstractBean;
Object expected = bean.get(); Object expected = bean.get();
@ -116,6 +104,7 @@ class LookupAnnotationTests {
@Test @Test
void testWithGenericBean() { void testWithGenericBean() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
beanFactory.registerBeanDefinition("numberBean", new RootBeanDefinition(NumberBean.class)); beanFactory.registerBeanDefinition("numberBean", new RootBeanDefinition(NumberBean.class));
beanFactory.registerBeanDefinition("doubleStore", new RootBeanDefinition(DoubleStore.class)); beanFactory.registerBeanDefinition("doubleStore", new RootBeanDefinition(DoubleStore.class));
beanFactory.registerBeanDefinition("floatStore", new RootBeanDefinition(FloatStore.class)); beanFactory.registerBeanDefinition("floatStore", new RootBeanDefinition(FloatStore.class));
@ -127,6 +116,7 @@ class LookupAnnotationTests {
@Test @Test
void testSingletonWithoutMetadataCaching() { void testSingletonWithoutMetadataCaching() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
beanFactory.setCacheBeanMetadata(false); beanFactory.setCacheBeanMetadata(false);
beanFactory.registerBeanDefinition("numberBean", new RootBeanDefinition(NumberBean.class)); beanFactory.registerBeanDefinition("numberBean", new RootBeanDefinition(NumberBean.class));
@ -140,6 +130,7 @@ class LookupAnnotationTests {
@Test @Test
void testPrototypeWithoutMetadataCaching() { void testPrototypeWithoutMetadataCaching() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
beanFactory.setCacheBeanMetadata(false); beanFactory.setCacheBeanMetadata(false);
beanFactory.registerBeanDefinition("numberBean", new RootBeanDefinition(NumberBean.class, BeanDefinition.SCOPE_PROTOTYPE, null)); beanFactory.registerBeanDefinition("numberBean", new RootBeanDefinition(NumberBean.class, BeanDefinition.SCOPE_PROTOTYPE, null));
@ -155,6 +146,23 @@ class LookupAnnotationTests {
assertThat(beanFactory.getBean(FloatStore.class)).isSameAs(bean.getFloatStore()); assertThat(beanFactory.getBean(FloatStore.class)).isSameAs(bean.getFloatStore());
} }
private DefaultListableBeanFactory configureBeanFactory(RootBeanDefinition tbd) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
AutowiredAnnotationBeanPostProcessor aabpp = new AutowiredAnnotationBeanPostProcessor();
aabpp.setBeanFactory(beanFactory);
beanFactory.addBeanPostProcessor(aabpp);
beanFactory.registerBeanDefinition("abstractBean", new RootBeanDefinition(AbstractBean.class));
beanFactory.registerBeanDefinition("beanConsumer", new RootBeanDefinition(BeanConsumer.class));
beanFactory.registerBeanDefinition("testBean", tbd);
return beanFactory;
}
private DefaultListableBeanFactory configureBeanFactory() {
RootBeanDefinition tbd = new RootBeanDefinition(TestBean.class);
tbd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
return configureBeanFactory(tbd);
}
public abstract static class AbstractBean { public abstract static class AbstractBean {

3
spring-beans/src/test/java/org/springframework/beans/factory/xml/DuplicateBeanIdTests.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -52,6 +52,7 @@ class DuplicateBeanIdTests {
@Test @Test
void duplicateBeanIdsAcrossNestingLevels() { void duplicateBeanIdsAcrossNestingLevels() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.setAllowBeanDefinitionOverriding(true);
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
reader.loadBeanDefinitions(new ClassPathResource("DuplicateBeanIdTests-multiLevel-context.xml", this.getClass())); reader.loadBeanDefinitions(new ClassPathResource("DuplicateBeanIdTests-multiLevel-context.xml", this.getClass()));
TestBean testBean = bf.getBean(TestBean.class); // there should be only one TestBean testBean = bf.getBean(TestBean.class); // there should be only one

1
spring-beans/src/test/java/org/springframework/beans/factory/xml/NestedBeansElementTests.java

@ -51,6 +51,7 @@ class NestedBeansElementTests {
env.setActiveProfiles("dev"); env.setActiveProfiles("dev");
DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.setAllowBeanDefinitionOverriding(true);
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
reader.setEnvironment(env); reader.setEnvironment(env);
reader.loadBeanDefinitions(XML); reader.loadBeanDefinitions(XML);

46
spring-context-support/src/test/java/org/springframework/cache/jcache/config/JCacheCustomInterceptorTests.java vendored

@ -24,6 +24,9 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cache.Cache; import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager; import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.annotation.EnableCaching;
@ -43,6 +46,8 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatRuntimeException; import static org.assertj.core.api.Assertions.assertThatRuntimeException;
/** /**
* Tests that use a custom {@link JCacheInterceptor}.
*
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
class JCacheCustomInterceptorTests { class JCacheCustomInterceptorTests {
@ -56,16 +61,19 @@ class JCacheCustomInterceptorTests {
@BeforeEach @BeforeEach
void setup() { void setup() {
ctx = new AnnotationConfigApplicationContext(EnableCachingConfig.class); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getBeanFactory().addBeanPostProcessor(
new CacheInterceptorBeanPostProcessor(context.getBeanFactory()));
context.register(EnableCachingConfig.class);
context.refresh();
this.ctx = context;
cs = ctx.getBean("service", JCacheableService.class); cs = ctx.getBean("service", JCacheableService.class);
exceptionCache = ctx.getBean("exceptionCache", Cache.class); exceptionCache = ctx.getBean("exceptionCache", Cache.class);
} }
@AfterEach @AfterEach
void tearDown() { void tearDown() {
if (ctx != null) { ctx.close();
ctx.close();
}
} }
@ -87,8 +95,8 @@ class JCacheCustomInterceptorTests {
@Test @Test
void customInterceptorAppliesWithCheckedException() { void customInterceptorAppliesWithCheckedException() {
assertThatRuntimeException() assertThatRuntimeException()
.isThrownBy(() -> cs.cacheWithCheckedException("id", true)) .isThrownBy(() -> cs.cacheWithCheckedException("id", true))
.withCauseExactlyInstanceOf(IOException.class); .withCauseExactlyInstanceOf(IOException.class);
} }
@ -120,18 +128,28 @@ class JCacheCustomInterceptorTests {
return new ConcurrentMapCache("exception"); return new ConcurrentMapCache("exception");
} }
@Bean
public JCacheInterceptor jCacheInterceptor(JCacheOperationSource cacheOperationSource) {
JCacheInterceptor cacheInterceptor = new TestCacheInterceptor();
cacheInterceptor.setCacheOperationSource(cacheOperationSource);
return cacheInterceptor;
}
} }
static class CacheInterceptorBeanPostProcessor implements BeanPostProcessor {
private final BeanFactory beanFactory;
CacheInterceptorBeanPostProcessor(BeanFactory beanFactory) {this.beanFactory = beanFactory;}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("jCacheInterceptor")) {
JCacheInterceptor cacheInterceptor = new TestCacheInterceptor();
cacheInterceptor.setCacheOperationSource(beanFactory.getBean(JCacheOperationSource.class));
return cacheInterceptor;
}
return bean;
}
}
/** /**
* A test {@link org.springframework.cache.interceptor.CacheInterceptor} that handles special exception * A test {@link JCacheInterceptor} that handles special exception types.
* types.
*/ */
@SuppressWarnings("serial") @SuppressWarnings("serial")
static class TestCacheInterceptor extends JCacheInterceptor { static class TestCacheInterceptor extends JCacheInterceptor {

39
spring-context/src/test/java/org/springframework/cache/config/CustomInterceptorTests.java vendored

@ -23,6 +23,9 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cache.CacheManager; import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheInterceptor; import org.springframework.cache.interceptor.CacheInterceptor;
@ -40,6 +43,8 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThatThrownBy;
/** /**
* Tests that use a custom {@link CacheInterceptor}.
*
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
class CustomInterceptorTests { class CustomInterceptorTests {
@ -50,7 +55,12 @@ class CustomInterceptorTests {
@BeforeEach @BeforeEach
void setup() { void setup() {
this.ctx = new AnnotationConfigApplicationContext(EnableCachingConfig.class); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getBeanFactory().addBeanPostProcessor(
new CacheInterceptorBeanPostProcessor(context.getBeanFactory()));
context.register(EnableCachingConfig.class);
context.refresh();
this.ctx = context;
this.cs = ctx.getBean("service", CacheableService.class); this.cs = ctx.getBean("service", CacheableService.class);
} }
@ -59,6 +69,7 @@ class CustomInterceptorTests {
this.ctx.close(); this.ctx.close();
} }
@Test @Test
void onlyOneInterceptorIsAvailable() { void onlyOneInterceptorIsAvailable() {
Map<String, CacheInterceptor> interceptors = this.ctx.getBeansOfType(CacheInterceptor.class); Map<String, CacheInterceptor> interceptors = this.ctx.getBeansOfType(CacheInterceptor.class);
@ -96,18 +107,28 @@ class CustomInterceptorTests {
return new DefaultCacheableService(); return new DefaultCacheableService();
} }
@Bean }
public CacheInterceptor cacheInterceptor(CacheOperationSource cacheOperationSource) {
CacheInterceptor cacheInterceptor = new TestCacheInterceptor(); static class CacheInterceptorBeanPostProcessor implements BeanPostProcessor {
cacheInterceptor.setCacheManager(cacheManager());
cacheInterceptor.setCacheOperationSources(cacheOperationSource); private final BeanFactory beanFactory;
return cacheInterceptor;
CacheInterceptorBeanPostProcessor(BeanFactory beanFactory) {this.beanFactory = beanFactory;}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("cacheInterceptor")) {
CacheInterceptor cacheInterceptor = new TestCacheInterceptor();
cacheInterceptor.setCacheManager(beanFactory.getBean(CacheManager.class));
cacheInterceptor.setCacheOperationSource(beanFactory.getBean(CacheOperationSource.class));
return cacheInterceptor;
}
return bean;
} }
} }
/** /**
* A test {@link CacheInterceptor} that handles special exception * A test {@link CacheInterceptor} that handles special exception types.
* types.
*/ */
@SuppressWarnings("serial") @SuppressWarnings("serial")
static class TestCacheInterceptor extends CacheInterceptor { static class TestCacheInterceptor extends CacheInterceptor {

5
spring-context/src/test/java/org/springframework/context/annotation/BeanMethodPolymorphismTests.java

@ -197,7 +197,10 @@ public class BeanMethodPolymorphismTests {
*/ */
@Test @Test
void beanMethodShadowing() { void beanMethodShadowing() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ShadowConfig.class); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.setAllowBeanDefinitionOverriding(true);
ctx.register(ShadowConfig.class);
ctx.refresh();
assertThat(ctx.getBean(String.class)).isEqualTo("shadow"); assertThat(ctx.getBean(String.class)).isEqualTo("shadow");
} }

1
spring-context/src/test/java/org/springframework/context/annotation/ClassPathBeanDefinitionScannerTests.java

@ -194,6 +194,7 @@ class ClassPathBeanDefinitionScannerTests {
@Test @Test
void testSimpleScanWithDefaultFiltersAndOverridingBean() { void testSimpleScanWithDefaultFiltersAndOverridingBean() {
GenericApplicationContext context = new GenericApplicationContext(); GenericApplicationContext context = new GenericApplicationContext();
context.setAllowBeanDefinitionOverriding(true);
context.registerBeanDefinition("stubFooDao", new RootBeanDefinition(TestBean.class)); context.registerBeanDefinition("stubFooDao", new RootBeanDefinition(TestBean.class));
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.setIncludeAnnotationConfig(false); scanner.setIncludeAnnotationConfig(false);

8
spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java

@ -329,6 +329,7 @@ class ConfigurationClassPostProcessorTests {
@Test @Test
void postProcessorOverridesNonApplicationBeanDefinitions() { void postProcessorOverridesNonApplicationBeanDefinitions() {
beanFactory.setAllowBeanDefinitionOverriding(true);
RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class); RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
rbd.setRole(RootBeanDefinition.ROLE_SUPPORT); rbd.setRole(RootBeanDefinition.ROLE_SUPPORT);
beanFactory.registerBeanDefinition("bar", rbd); beanFactory.registerBeanDefinition("bar", rbd);
@ -342,6 +343,7 @@ class ConfigurationClassPostProcessorTests {
@Test @Test
void postProcessorDoesNotOverrideRegularBeanDefinitions() { void postProcessorDoesNotOverrideRegularBeanDefinitions() {
beanFactory.setAllowBeanDefinitionOverriding(true);
RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class); RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
rbd.setResource(new DescriptiveResource("XML or something")); rbd.setResource(new DescriptiveResource("XML or something"));
beanFactory.registerBeanDefinition("bar", rbd); beanFactory.registerBeanDefinition("bar", rbd);
@ -354,6 +356,7 @@ class ConfigurationClassPostProcessorTests {
@Test @Test
void postProcessorDoesNotOverrideRegularBeanDefinitionsEvenWithScopedProxy() { void postProcessorDoesNotOverrideRegularBeanDefinitionsEvenWithScopedProxy() {
beanFactory.setAllowBeanDefinitionOverriding(true);
RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class); RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
rbd.setResource(new DescriptiveResource("XML or something")); rbd.setResource(new DescriptiveResource("XML or something"));
BeanDefinitionHolder proxied = ScopedProxyUtils.createScopedProxy( BeanDefinitionHolder proxied = ScopedProxyUtils.createScopedProxy(
@ -396,6 +399,7 @@ class ConfigurationClassPostProcessorTests {
@Test @Test
void configurationClassesProcessedInCorrectOrder() { void configurationClassesProcessedInCorrectOrder() {
beanFactory.setAllowBeanDefinitionOverriding(true);
beanFactory.registerBeanDefinition("config1", new RootBeanDefinition(OverridingSingletonBeanConfig.class)); beanFactory.registerBeanDefinition("config1", new RootBeanDefinition(OverridingSingletonBeanConfig.class));
beanFactory.registerBeanDefinition("config2", new RootBeanDefinition(SingletonBeanConfig.class)); beanFactory.registerBeanDefinition("config2", new RootBeanDefinition(SingletonBeanConfig.class));
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
@ -410,6 +414,7 @@ class ConfigurationClassPostProcessorTests {
@Test @Test
void configurationClassesWithValidOverridingForProgrammaticCall() { void configurationClassesWithValidOverridingForProgrammaticCall() {
beanFactory.setAllowBeanDefinitionOverriding(true);
beanFactory.registerBeanDefinition("config1", new RootBeanDefinition(OverridingAgainSingletonBeanConfig.class)); beanFactory.registerBeanDefinition("config1", new RootBeanDefinition(OverridingAgainSingletonBeanConfig.class));
beanFactory.registerBeanDefinition("config2", new RootBeanDefinition(OverridingSingletonBeanConfig.class)); beanFactory.registerBeanDefinition("config2", new RootBeanDefinition(OverridingSingletonBeanConfig.class));
beanFactory.registerBeanDefinition("config3", new RootBeanDefinition(SingletonBeanConfig.class)); beanFactory.registerBeanDefinition("config3", new RootBeanDefinition(SingletonBeanConfig.class));
@ -425,6 +430,7 @@ class ConfigurationClassPostProcessorTests {
@Test @Test
void configurationClassesWithInvalidOverridingForProgrammaticCall() { void configurationClassesWithInvalidOverridingForProgrammaticCall() {
beanFactory.setAllowBeanDefinitionOverriding(true);
beanFactory.registerBeanDefinition("config1", new RootBeanDefinition(InvalidOverridingSingletonBeanConfig.class)); beanFactory.registerBeanDefinition("config1", new RootBeanDefinition(InvalidOverridingSingletonBeanConfig.class));
beanFactory.registerBeanDefinition("config2", new RootBeanDefinition(OverridingSingletonBeanConfig.class)); beanFactory.registerBeanDefinition("config2", new RootBeanDefinition(OverridingSingletonBeanConfig.class));
beanFactory.registerBeanDefinition("config3", new RootBeanDefinition(SingletonBeanConfig.class)); beanFactory.registerBeanDefinition("config3", new RootBeanDefinition(SingletonBeanConfig.class));
@ -441,6 +447,7 @@ class ConfigurationClassPostProcessorTests {
@Test // SPR-15384 @Test // SPR-15384
void nestedConfigurationClassesProcessedInCorrectOrder() { void nestedConfigurationClassesProcessedInCorrectOrder() {
beanFactory.setAllowBeanDefinitionOverriding(true);
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(ConfigWithOrderedNestedClasses.class)); beanFactory.registerBeanDefinition("config", new RootBeanDefinition(ConfigWithOrderedNestedClasses.class));
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.postProcessBeanFactory(beanFactory); pp.postProcessBeanFactory(beanFactory);
@ -454,6 +461,7 @@ class ConfigurationClassPostProcessorTests {
@Test // SPR-16734 @Test // SPR-16734
void innerConfigurationClassesProcessedInCorrectOrder() { void innerConfigurationClassesProcessedInCorrectOrder() {
beanFactory.setAllowBeanDefinitionOverriding(true);
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(ConfigWithOrderedInnerClasses.class)); beanFactory.registerBeanDefinition("config", new RootBeanDefinition(ConfigWithOrderedInnerClasses.class));
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
pp.postProcessBeanFactory(beanFactory); pp.postProcessBeanFactory(beanFactory);

5
spring-context/src/test/java/org/springframework/context/annotation/EnableAspectJAutoProxyTests.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2022 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -23,6 +23,7 @@ import example.scannable.FooDao;
import example.scannable.FooService; import example.scannable.FooService;
import example.scannable.FooServiceImpl; import example.scannable.FooServiceImpl;
import example.scannable.ServiceInvocationCounter; import example.scannable.ServiceInvocationCounter;
import example.scannable.StubFooDao;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Before;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -123,7 +124,7 @@ class EnableAspectJAutoProxyTests {
} }
@ComponentScan("example.scannable") @Import({ ServiceInvocationCounter.class, StubFooDao.class })
@EnableAspectJAutoProxy(exposeProxy = true) @EnableAspectJAutoProxy(exposeProxy = true)
static class ConfigWithExposedProxy { static class ConfigWithExposedProxy {

8
spring-context/src/test/java/org/springframework/context/annotation/NestedConfigurationClassTests.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -36,6 +36,7 @@ class NestedConfigurationClassTests {
@Test @Test
void oneLevelDeep() { void oneLevelDeep() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.setAllowBeanDefinitionOverriding(true);
ctx.register(L0Config.L1Config.class); ctx.register(L0Config.L1Config.class);
ctx.refresh(); ctx.refresh();
@ -55,6 +56,7 @@ class NestedConfigurationClassTests {
@Test @Test
void twoLevelsDeep() { void twoLevelsDeep() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.setAllowBeanDefinitionOverriding(true);
ctx.register(L0Config.class); ctx.register(L0Config.class);
ctx.refresh(); ctx.refresh();
@ -78,6 +80,7 @@ class NestedConfigurationClassTests {
@Test @Test
void twoLevelsInLiteMode() { void twoLevelsInLiteMode() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.setAllowBeanDefinitionOverriding(true);
ctx.register(L0ConfigLight.class); ctx.register(L0ConfigLight.class);
ctx.refresh(); ctx.refresh();
@ -101,6 +104,7 @@ class NestedConfigurationClassTests {
@Test @Test
void twoLevelsDeepWithInheritance() { void twoLevelsDeepWithInheritance() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.setAllowBeanDefinitionOverriding(true);
ctx.register(S1Config.class); ctx.register(S1Config.class);
ctx.refresh(); ctx.refresh();
@ -130,6 +134,7 @@ class NestedConfigurationClassTests {
@Test @Test
void twoLevelsDeepWithInheritanceThroughImport() { void twoLevelsDeepWithInheritanceThroughImport() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.setAllowBeanDefinitionOverriding(true);
ctx.register(S1Importer.class); ctx.register(S1Importer.class);
ctx.refresh(); ctx.refresh();
@ -159,6 +164,7 @@ class NestedConfigurationClassTests {
@Test @Test
void twoLevelsDeepWithInheritanceAndScopedProxy() { void twoLevelsDeepWithInheritanceAndScopedProxy() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.setAllowBeanDefinitionOverriding(true);
ctx.register(S1ImporterWithProxy.class); ctx.register(S1ImporterWithProxy.class);
ctx.refresh(); ctx.refresh();

1
spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportAnnotationDetectionTests.java

@ -65,6 +65,7 @@ public class ImportAnnotationDetectionTests {
@Test @Test
void localImportIsProcessedLast() { void localImportIsProcessedLast() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.setAllowBeanDefinitionOverriding(true);
ctx.register(MultiMetaImportConfigWithLocalImportWithBeanOverride.class); ctx.register(MultiMetaImportConfigWithLocalImportWithBeanOverride.class);
ctx.refresh(); ctx.refresh();
assertThat(ctx.containsBean("testBean1")).isTrue(); assertThat(ctx.containsBean("testBean1")).isTrue();

2
spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportTests.java

@ -181,6 +181,7 @@ class ImportTests {
@Test @Test
void testImportAnnotationWithMultipleArgumentsResultingInOverriddenBeanDefinition() { void testImportAnnotationWithMultipleArgumentsResultingInOverriddenBeanDefinition() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.setAllowBeanDefinitionOverriding(true);
beanFactory.registerBeanDefinition("config", new RootBeanDefinition( beanFactory.registerBeanDefinition("config", new RootBeanDefinition(
WithMultipleArgumentsThatWillCauseDuplication.class)); WithMultipleArgumentsThatWillCauseDuplication.class));
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
@ -380,6 +381,7 @@ class ImportTests {
@Test // gh-24643 @Test // gh-24643
void importedConfigOverridesScanned() { void importedConfigOverridesScanned() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.setAllowBeanDefinitionOverriding(true);
ctx.scan(SiblingImportingConfigA.class.getPackage().getName()); ctx.scan(SiblingImportingConfigA.class.getPackage().getName());
ctx.refresh(); ctx.refresh();

2
spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java

@ -96,6 +96,7 @@ class EnableAsyncTests {
@Test @Test
void properExceptionForExistingProxyDependencyMismatch() { void properExceptionForExistingProxyDependencyMismatch() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.setAllowBeanDefinitionOverriding(true);
ctx.register(AsyncConfig.class, AsyncBeanWithInterface.class, AsyncBeanUser.class); ctx.register(AsyncConfig.class, AsyncBeanWithInterface.class, AsyncBeanUser.class);
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(ctx::refresh) assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(ctx::refresh)
.withCauseInstanceOf(BeanNotOfRequiredTypeException.class); .withCauseInstanceOf(BeanNotOfRequiredTypeException.class);
@ -105,6 +106,7 @@ class EnableAsyncTests {
@Test @Test
void properExceptionForResolvedProxyDependencyMismatch() { void properExceptionForResolvedProxyDependencyMismatch() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.setAllowBeanDefinitionOverriding(true);
ctx.register(AsyncConfig.class, AsyncBeanUser.class, AsyncBeanWithInterface.class); ctx.register(AsyncConfig.class, AsyncBeanUser.class, AsyncBeanWithInterface.class);
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(ctx::refresh) assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(ctx::refresh)
.withCauseInstanceOf(BeanNotOfRequiredTypeException.class); .withCauseInstanceOf(BeanNotOfRequiredTypeException.class);

4
spring-test/src/test/java/org/springframework/test/context/junit4/ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -31,7 +31,7 @@ import org.springframework.util.ResourceUtils;
* @see AbsolutePathSpringJUnit4ClassRunnerAppCtxTests * @see AbsolutePathSpringJUnit4ClassRunnerAppCtxTests
* @see RelativePathSpringJUnit4ClassRunnerAppCtxTests * @see RelativePathSpringJUnit4ClassRunnerAppCtxTests
*/ */
@ContextConfiguration(locations = { ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests.CLASSPATH_CONTEXT_RESOURCE_PATH }) @ContextConfiguration(locations = { ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests.CLASSPATH_CONTEXT_RESOURCE_PATH }, inheritLocations = false)
public class ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests extends SpringJUnit4ClassRunnerAppCtxTests { public class ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests extends SpringJUnit4ClassRunnerAppCtxTests {
/** /**

Loading…
Cancel
Save