diff --git a/spring-context/src/main/java/org/springframework/context/annotation/Configuration.java b/spring-context/src/main/java/org/springframework/context/annotation/Configuration.java index abdd2a44e312..7d8546cdad17 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/Configuration.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/Configuration.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. @@ -344,9 +344,9 @@ * *
By default, {@code @Bean} methods will be eagerly instantiated at container * bootstrap time. To avoid this, {@code @Configuration} may be used in conjunction with - * the {@link Lazy @Lazy} annotation to indicate that all {@code @Bean} methods declared within - * the class are by default lazily initialized. Note that {@code @Lazy} may be used on - * individual {@code @Bean} methods as well. + * the {@link Lazy @Lazy} annotation to indicate that all {@code @Bean} methods declared + * within the class are by default lazily initialized. Note that {@code @Lazy} may be used + * on individual {@code @Bean} methods as well. * *
The default is {@code true}, allowing for 'inter-bean references' within + * the configuration class as well as for external calls to this configuration's + * {@code @Bean} methods, e.g. from another configuration class. If this is not + * needed since each of this particular configuration's {@code @Bean} methods + * is self-contained and designed as a plain factory method for container use, + * switch this flag to {@code false} in order to avoid CGLIB subclass processing. + *
Turning off bean method interception effectively processes {@code @Bean}
+ * methods individually like when declared on non-{@code @Configuration} classes,
+ * a.k.a. "@Bean Lite Mode" (see {@link Bean @Bean's javadoc}). It is therefore
+ * behaviorally equivalent to removing the {@code @Configuration} stereotype.
+ * @since 5.2
+ */
+ boolean proxyBeanMethods() default true;
+
}
diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java
index 5ada7b5b8f31..22e735da59a6 100644
--- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java
+++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -112,10 +112,11 @@ else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)
}
}
- if (isFullConfigurationCandidate(metadata)) {
+ Map Technically, {@link ConfigurationClassPostProcessor} could fail to enhance the
* registered Configuration classes and many use cases would still work.
* Certain cases, however, like inter-bean singleton references would not.
- * We test for such a case below, and in doing so prove that enhancement is
- * working.
+ * We test for such a case below, and in doing so prove that enhancement is working.
*/
@Test
public void enhancementIsPresentBecauseSingletonSemanticsAreRespected() {
@@ -104,6 +103,16 @@ public void enhancementIsPresentBecauseSingletonSemanticsAreRespected() {
assertTrue(Arrays.asList(beanFactory.getDependentBeans("foo")).contains("bar"));
}
+ @Test
+ public void enhancementIsNotPresentForProxyBeanMethodsFlagSetToFalse() {
+ beanFactory.registerBeanDefinition("config", new RootBeanDefinition(NonEnhancedSingletonBeanConfig.class));
+ ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
+ pp.postProcessBeanFactory(beanFactory);
+ Foo foo = beanFactory.getBean("foo", Foo.class);
+ Bar bar = beanFactory.getBean("bar", Bar.class);
+ assertNotSame(foo, bar.foo);
+ }
+
@Test
public void configurationIntrospectionOfInnerClassesWorksWithDotNameSyntax() {
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(getClass().getName() + ".SingletonBeanConfig"));
@@ -115,8 +124,8 @@ public void configurationIntrospectionOfInnerClassesWorksWithDotNameSyntax() {
}
/**
- * Tests the fix for SPR-5655, a special workaround that prefers reflection
- * over ASM if a bean class is already loaded.
+ * Tests the fix for SPR-5655, a special workaround that prefers reflection over ASM
+ * if a bean class is already loaded.
*/
@Test
public void alreadyLoadedConfigurationClasses() {
@@ -129,8 +138,7 @@ public void alreadyLoadedConfigurationClasses() {
}
/**
- * Tests whether a bean definition without a specified bean class is handled
- * correctly.
+ * Tests whether a bean definition without a specified bean class is handled correctly.
*/
@Test
public void postProcessorIntrospectsInheritedDefinitionsCorrectly() {
@@ -1070,6 +1078,18 @@ static class SingletonBeanConfig {
}
}
+ @Configuration(proxyBeanMethods = false)
+ static class NonEnhancedSingletonBeanConfig {
+
+ public @Bean Foo foo() {
+ return new Foo();
+ }
+
+ public @Bean Bar bar() {
+ return new Bar(foo());
+ }
+ }
+
@Configuration
@Order(2)
static class OverridingSingletonBeanConfig {