resolved:
+ Provide @Primary annotation (SPR-5590) + Provide @Lazy annotation (SPR-5591) + Test @Bean initMethod/destroyMethod functionality (SPR-5592) + Test @Bean dependsOn functionality (SPR-5593) git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@866 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
parent
33137847a3
commit
eac93ebd59
|
|
@ -77,14 +77,19 @@ public @interface Bean {
|
|||
/**
|
||||
* The optional name of a method to call on the bean instance during initialization.
|
||||
* Not commonly used, given that the method may be called programmatically directly
|
||||
* within the Bean method.
|
||||
* within the body of a Bean-annotated method.
|
||||
*/
|
||||
String initMethod() default "";
|
||||
|
||||
/**
|
||||
* The optional name of a method to call on the bean instance during upon closing
|
||||
* the application context, for example a {@literal close()}
|
||||
* method on a {@literal DataSource}.
|
||||
* method on a {@literal DataSource}. The method must have no arguments, but may
|
||||
* throw any exception.
|
||||
* <p>Note: Only invoked on beans whose lifecycle is under the full control of the
|
||||
* factory which is always the case for singletons, but not guaranteed
|
||||
* for any other scope.
|
||||
* see {@link org.springframework.context.ConfigurableApplicationContext#close()}
|
||||
*/
|
||||
String destroyMethod() default "";
|
||||
|
||||
|
|
@ -93,6 +98,8 @@ public @interface Bean {
|
|||
* created by the container before this bean. Used infrequently in cases where a bean
|
||||
* does not explicitly depend on another through properties or constructor arguments,
|
||||
* but rather depends on the side effects of another bean's initialization.
|
||||
* <p>Note: This attribute will not be inherited by child bean definitions,
|
||||
* hence it needs to be specified per concrete bean definition.
|
||||
*/
|
||||
String[] dependsOn() default {};
|
||||
|
||||
|
|
|
|||
|
|
@ -85,10 +85,10 @@ final class BeanMethod implements BeanMetadataElement {
|
|||
* @see #getRequiredAnnotation(Class)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Annotation> T getAnnotation(Class<T> annoType) {
|
||||
public <A extends Annotation> A getAnnotation(Class<A> annoType) {
|
||||
for (Annotation anno : annotations)
|
||||
if (anno.annotationType().equals(annoType))
|
||||
return (T) anno;
|
||||
return (A) anno;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
@ -101,7 +101,9 @@ final class BeanMethod implements BeanMetadataElement {
|
|||
public <T extends Annotation> T getRequiredAnnotation(Class<T> annoType) {
|
||||
T anno = getAnnotation(annoType);
|
||||
|
||||
Assert.notNull(anno, format("annotation %s not found on %s", annoType.getSimpleName(), this));
|
||||
if(anno == null)
|
||||
throw new IllegalStateException(
|
||||
format("required annotation %s is not present on %s", annoType.getSimpleName(), this));
|
||||
|
||||
return anno;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,13 +55,13 @@ import org.springframework.stereotype.Component;
|
|||
* @see Bean
|
||||
* @see Lazy
|
||||
* @see Value
|
||||
* @see org.springframework.context.annotation.support.ConfigurationClassPostProcessor;
|
||||
* @see ConfigurationClassPostProcessor;
|
||||
*/
|
||||
@Component
|
||||
@Target( { ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
@Component
|
||||
public @interface Configuration {
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package org.springframework.context.annotation;
|
|||
|
||||
import static java.lang.String.*;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
|
@ -43,7 +44,7 @@ final class ConfigurationClass extends ModelClass {
|
|||
|
||||
private String beanName;
|
||||
private int modifiers;
|
||||
private Configuration configurationAnnotation;
|
||||
private HashSet<Annotation> annotations = new HashSet<Annotation>();
|
||||
private HashSet<BeanMethod> methods = new HashSet<BeanMethod>();
|
||||
private ConfigurationClass declaringClass;
|
||||
|
||||
|
|
@ -63,14 +64,38 @@ final class ConfigurationClass extends ModelClass {
|
|||
Assert.isTrue(modifiers >= 0, "modifiers must be non-negative");
|
||||
this.modifiers = modifiers;
|
||||
}
|
||||
|
||||
public Configuration getConfigurationAnnotation() {
|
||||
return this.configurationAnnotation;
|
||||
|
||||
public void addAnnotation(Annotation annotation) {
|
||||
this.annotations.add(annotation);
|
||||
}
|
||||
|
||||
public void setConfigurationAnnotation(Configuration configAnno) {
|
||||
Assert.notNull(configAnno, "configuration annotation must be non-null");
|
||||
this.configurationAnnotation = configAnno;
|
||||
/**
|
||||
* @return the annotation on this class matching <var>annoType</var> or
|
||||
* {@literal null} if not present.
|
||||
* @see #getRequiredAnnotation(Class)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <A extends Annotation> A getAnnotation(Class<A> annoType) {
|
||||
for (Annotation annotation : annotations)
|
||||
if(annotation.annotationType().equals(annoType))
|
||||
return (A) annotation;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the annotation on this class matching <var>annoType</var>
|
||||
* @throws {@link IllegalStateException} if not present
|
||||
* @see #getAnnotation(Class)
|
||||
*/
|
||||
public <A extends Annotation> A getRequiredAnnotation(Class<A> annoType) {
|
||||
A anno = getAnnotation(annoType);
|
||||
|
||||
if(anno == null)
|
||||
throw new IllegalStateException(
|
||||
format("required annotation %s is not present on %s", annoType.getSimpleName(), this));
|
||||
|
||||
return anno;
|
||||
}
|
||||
|
||||
public Set<BeanMethod> getBeanMethods() {
|
||||
|
|
@ -93,7 +118,7 @@ final class ConfigurationClass extends ModelClass {
|
|||
|
||||
public void validate(ProblemReporter problemReporter) {
|
||||
// configuration classes must be annotated with @Configuration
|
||||
if (configurationAnnotation == null)
|
||||
if (getAnnotation(Configuration.class) == null)
|
||||
problemReporter.error(new NonAnnotatedConfigurationProblem());
|
||||
|
||||
// a configuration class may not be final (CGLIB limitation)
|
||||
|
|
@ -113,9 +138,12 @@ final class ConfigurationClass extends ModelClass {
|
|||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = super.hashCode();
|
||||
result = prime * result + ((declaringClass == null) ? 0 : declaringClass.hashCode());
|
||||
result = prime * result + ((beanName == null) ? 0 : beanName.hashCode());
|
||||
result = prime * result + ((configurationAnnotation == null) ? 0 : configurationAnnotation.hashCode());
|
||||
result = prime * result
|
||||
+ ((annotations == null) ? 0 : annotations.hashCode());
|
||||
result = prime * result
|
||||
+ ((beanName == null) ? 0 : beanName.hashCode());
|
||||
result = prime * result
|
||||
+ ((declaringClass == null) ? 0 : declaringClass.hashCode());
|
||||
result = prime * result + ((methods == null) ? 0 : methods.hashCode());
|
||||
result = prime * result + modifiers;
|
||||
return result;
|
||||
|
|
@ -130,20 +158,20 @@ final class ConfigurationClass extends ModelClass {
|
|||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ConfigurationClass other = (ConfigurationClass) obj;
|
||||
if (declaringClass == null) {
|
||||
if (other.declaringClass != null)
|
||||
if (annotations == null) {
|
||||
if (other.annotations != null)
|
||||
return false;
|
||||
} else if (!declaringClass.equals(other.declaringClass))
|
||||
} else if (!annotations.equals(other.annotations))
|
||||
return false;
|
||||
if (beanName == null) {
|
||||
if (other.beanName != null)
|
||||
return false;
|
||||
} else if (!beanName.equals(other.beanName))
|
||||
return false;
|
||||
if (configurationAnnotation == null) {
|
||||
if (other.configurationAnnotation != null)
|
||||
if (declaringClass == null) {
|
||||
if (other.declaringClass != null)
|
||||
return false;
|
||||
} else if (!configurationAnnotation.equals(other.configurationAnnotation))
|
||||
} else if (!declaringClass.equals(other.declaringClass))
|
||||
return false;
|
||||
if (methods == null) {
|
||||
if (other.methods != null)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import static java.lang.String.*;
|
|||
import static org.springframework.context.annotation.AsmUtils.*;
|
||||
import static org.springframework.util.ClassUtils.*;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.HashMap;
|
||||
import java.util.Stack;
|
||||
|
||||
|
|
@ -105,26 +106,27 @@ class ConfigurationClassVisitor extends ClassAdapter {
|
|||
|
||||
/**
|
||||
* Visits a class level annotation on a {@link Configuration @Configuration} class.
|
||||
* Accounts for all possible class-level annotations that are respected by JavaConfig
|
||||
* including AspectJ's {@code @Aspect} annotation.
|
||||
* <p>
|
||||
* Upon encountering such an annotation, update the {@link #configClass} model object
|
||||
* appropriately, and then return an {@link AnnotationVisitor} implementation that can
|
||||
* populate the annotation appropriately with data.
|
||||
*
|
||||
* <p>Upon encountering such an annotation, updates the {@link #configClass} model
|
||||
* object appropriately, and then returns an {@link AnnotationVisitor} implementation
|
||||
* that can populate the annotation appropriately with its attribute data as parsed
|
||||
* by ASM.
|
||||
*
|
||||
* @see MutableAnnotation
|
||||
* @see Configuration
|
||||
* @see Lazy
|
||||
* @see Import
|
||||
*/
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(String annoTypeDesc, boolean visible) {
|
||||
String annoTypeName = convertAsmTypeDescriptorToClassName(annoTypeDesc);
|
||||
Class<? extends Annotation> annoClass = loadToolingSafeClass(annoTypeName, classLoader);
|
||||
|
||||
if (Configuration.class.getName().equals(annoTypeName)) {
|
||||
Configuration mutableConfiguration = createMutableAnnotation(Configuration.class, classLoader);
|
||||
configClass.setConfigurationAnnotation(mutableConfiguration);
|
||||
return new MutableAnnotationVisitor(mutableConfiguration, classLoader);
|
||||
}
|
||||
if (annoClass == null)
|
||||
// annotation was unable to be loaded -> probably Spring IDE unable to load a user-defined annotation
|
||||
return super.visitAnnotation(annoTypeDesc, visible);
|
||||
|
||||
if (Import.class.getName().equals(annoTypeName)) {
|
||||
if (Import.class.equals(annoClass)) {
|
||||
ImportStack importStack = ImportStackHolder.getImportStack();
|
||||
|
||||
if (!importStack.contains(configClass)) {
|
||||
|
|
@ -135,7 +137,9 @@ class ConfigurationClassVisitor extends ClassAdapter {
|
|||
problemReporter.error(new CircularImportProblem(configClass, importStack));
|
||||
}
|
||||
|
||||
return super.visitAnnotation(annoTypeDesc, visible);
|
||||
Annotation mutableAnnotation = createMutableAnnotation(annoClass, classLoader);
|
||||
configClass.addAnnotation(mutableAnnotation);
|
||||
return new MutableAnnotationVisitor(mutableAnnotation, classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -187,7 +191,7 @@ class ConfigurationClassVisitor extends ClassAdapter {
|
|||
innerConfigClass.setDeclaringClass(innerClasses.get(outerName));
|
||||
|
||||
// is the inner class a @Configuration class? If so, add it to the list
|
||||
if (innerConfigClass.getConfigurationAnnotation() != null)
|
||||
if (innerConfigClass.getAnnotation(Configuration.class) != null)
|
||||
innerClasses.put(name, innerConfigClass);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -155,15 +155,16 @@ class ConfigurationModelBeanDefinitionReader {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: re-enable for Lazy support
|
||||
// // is this bean marked as primary for disambiguation?
|
||||
// if (bean.primary() == Primary.TRUE)
|
||||
// beanDef.setPrimary(true);
|
||||
//
|
||||
// // is this bean lazily instantiated?
|
||||
// if ((bean.lazy() == Lazy.TRUE)
|
||||
// || ((bean.lazy() == Lazy.UNSPECIFIED) && (defaults.defaultLazy() == Lazy.TRUE)))
|
||||
// beanDef.setLazyInit(true);
|
||||
if (method.getAnnotation(Primary.class) != null)
|
||||
beanDef.setPrimary(true);
|
||||
|
||||
// is this bean to be instantiated lazily?
|
||||
Lazy defaultLazy = configClass.getAnnotation(Lazy.class);
|
||||
if (defaultLazy != null)
|
||||
beanDef.setLazyInit(defaultLazy.value());
|
||||
Lazy lazy = method.getAnnotation(Lazy.class);
|
||||
if (lazy != null)
|
||||
beanDef.setLazyInit(lazy.value());
|
||||
|
||||
// does this bean have a custom init-method specified?
|
||||
String initMethodName = bean.initMethod();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright 2002-2009 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates whether a bean is to be lazily initialized.
|
||||
*
|
||||
* <p>May be used on any class directly or indirectly annotated with
|
||||
* {@link org.springframework.stereotype.Component} or on methods annotated with
|
||||
* {@link Bean}.
|
||||
*
|
||||
* <p>If this annotation is not present on a Component or Bean definition, eager
|
||||
* initialization will occur. If present and set to {@literal true}, the
|
||||
* Bean/Component will not be initialized until referenced by another bean or
|
||||
* explicitly retrieved from the enclosing
|
||||
* {@link org.springframework.beans.factory.BeanFactory}. If present and set to
|
||||
* {@literal false}, the bean will be instantiated on startup by bean factories
|
||||
* that perform eager initialization of singletons.
|
||||
*
|
||||
* <p>If Lazy is present on a {@link Configuration} class, this indicates that all
|
||||
* {@link Bean} methods within that {@literal Configuration} should be lazily
|
||||
* initialized. If Lazy is present and false on a Bean method within a
|
||||
* Lazy-annotated Configuration class, this indicates overriding the 'default
|
||||
* lazy' behavior and that the bean should be eagerly initialized.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.0
|
||||
* @see Primary
|
||||
* @see Bean
|
||||
* @see Configuration
|
||||
* @see org.springframework.stereotype.Component
|
||||
*/
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Lazy {
|
||||
|
||||
/**
|
||||
* Whether lazy initialization should occur.
|
||||
*/
|
||||
boolean value() default true;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright 2002-2009 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates that a bean should be given preference when multiple candidates
|
||||
* are qualified to autowire a single-valued dependency. If exactly one 'primary'
|
||||
* bean exists among the candidates, it will be the autowired value.
|
||||
*
|
||||
* <p>May be used on any class directly or indirectly annotated with
|
||||
* {@link org.springframework.stereotype.Component} or on methods annotated
|
||||
* with {@link Bean}.
|
||||
*
|
||||
* <p>Using {@link Primary} at the class level has no effect unless component-scanning
|
||||
* is being used. If a {@link Primary}-annotated class is declared via XML,
|
||||
* {@link Primary} annotation metadata is ignored, and
|
||||
* {@literal <bean primary="true|false"/>} is respected instead.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.0
|
||||
* @see Lazy
|
||||
* @see Bean
|
||||
* @see org.springframework.stereotype.Component
|
||||
*/
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Primary {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright 2002-2009 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation.configuration;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests proving that the various attributes available via the {@link Bean}
|
||||
* annotation are correctly reflected in the {@link BeanDefinition} created when
|
||||
* processing the {@link Configuration} class.
|
||||
*
|
||||
* <p>Also includes tests proving that using {@link Lazy} and {@link Primary}
|
||||
* annotations in conjunction with Bean propagate their respective metadata
|
||||
* correctly into the resulting BeanDefinition
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
@SuppressWarnings("unused") // for unused @Bean methods in local classes
|
||||
public class BeanAnnotationAttributePropagationTests {
|
||||
|
||||
@Test
|
||||
public void initMethodMetadataIsPropagated() {
|
||||
@Configuration class Config {
|
||||
@Bean(initMethod="start") Object foo() { return null; }
|
||||
}
|
||||
|
||||
assertEquals("init method name was not propagated",
|
||||
"start", beanDef(Config.class).getInitMethodName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destroyMethodMetadataIsPropagated() {
|
||||
@Configuration class Config {
|
||||
@Bean(destroyMethod="destroy") Object foo() { return null; }
|
||||
}
|
||||
|
||||
assertEquals("destroy method name was not propagated",
|
||||
"destroy", beanDef(Config.class).getDestroyMethodName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dependsOnMetadataIsPropagated() {
|
||||
@Configuration class Config {
|
||||
@Bean(dependsOn={"bar", "baz"}) Object foo() { return null; }
|
||||
}
|
||||
|
||||
assertArrayEquals("dependsOn metadata was not propagated",
|
||||
new String[] {"bar", "baz"}, beanDef(Config.class).getDependsOn());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void primaryMetadataIsPropagated() {
|
||||
@Configuration class Config {
|
||||
@Primary @Bean
|
||||
Object foo() { return null; }
|
||||
}
|
||||
|
||||
assertTrue("primary metadata was not propagated",
|
||||
beanDef(Config.class).isPrimary());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void primaryMetadataIsFalseByDefault() {
|
||||
@Configuration class Config {
|
||||
@Bean Object foo() { return null; }
|
||||
}
|
||||
|
||||
assertFalse("@Bean methods should be non-primary by default",
|
||||
beanDef(Config.class).isPrimary());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lazyMetadataIsPropagated() {
|
||||
@Configuration class Config {
|
||||
@Lazy @Bean
|
||||
Object foo() { return null; }
|
||||
}
|
||||
|
||||
assertTrue("lazy metadata was not propagated",
|
||||
beanDef(Config.class).isLazyInit());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void lazyMetadataIsFalseByDefault() {
|
||||
@Configuration class Config {
|
||||
@Bean Object foo() { return null; }
|
||||
}
|
||||
|
||||
assertFalse("@Bean methods should be non-lazy by default",
|
||||
beanDef(Config.class).isLazyInit());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultLazyConfigurationPropagatesToIndividualBeans() {
|
||||
@Lazy @Configuration class Config {
|
||||
@Bean Object foo() { return null; }
|
||||
}
|
||||
|
||||
assertTrue("@Bean methods declared in a @Lazy @Configuration should be lazily instantiated",
|
||||
beanDef(Config.class).isLazyInit());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eagerBeanOverridesDefaultLazyConfiguration() {
|
||||
@Lazy @Configuration class Config {
|
||||
@Lazy(false) @Bean Object foo() { return null; }
|
||||
}
|
||||
|
||||
assertFalse("@Lazy(false) @Bean methods declared in a @Lazy @Configuration should be eagerly instantiated",
|
||||
beanDef(Config.class).isLazyInit());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eagerConfigurationProducesEagerBeanDefinitions() {
|
||||
@Lazy(false) @Configuration class Config { // will probably never happen, doesn't make much sense
|
||||
@Bean Object foo() { return null; }
|
||||
}
|
||||
|
||||
assertFalse("@Lazy(false) @Configuration should produce eager bean definitions",
|
||||
beanDef(Config.class).isLazyInit());
|
||||
}
|
||||
|
||||
private AbstractBeanDefinition beanDef(Class<?> configClass) {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
factory.registerBeanDefinition("config", new RootBeanDefinition(configClass));
|
||||
new ConfigurationClassPostProcessor().postProcessBeanFactory(factory);
|
||||
|
||||
return (AbstractBeanDefinition) factory.getBeanDefinition("foo");
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue