Browse Source
+ Provide @Primary annotation (SPR-5590) + Provide @Lazy annotation (SPR-5591) + Test @Bean initMethod/destroyMethod functionality (SPR-5592) + Test @Bean dependsOn functionality (SPR-5593)pull/23217/head
9 changed files with 360 additions and 46 deletions
@ -0,0 +1,64 @@
@@ -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 @@
@@ -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 @@
@@ -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