/* * 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 static java.lang.String.format; import java.util.Map; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import org.junit.Test; import static org.junit.matchers.JUnitMatchers.*; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation6.ComponentForScanning; import org.springframework.context.annotation6.ConfigForScanning; import org.springframework.context.annotation6.Jsr330NamedForScanning; import static org.springframework.util.StringUtils.*; /** * @author Chris Beams * @author Juergen Hoeller */ public class AnnotationConfigApplicationContextTests { @Test(expected=IllegalArgumentException.class) public void nullGetBeanParameterIsDisallowed() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class); context.getBean((Class<?>)null); } @Test public void scanAndRefresh() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.scan("org.springframework.context.annotation6"); context.refresh(); context.getBean(uncapitalize(ConfigForScanning.class.getSimpleName())); context.getBean("testBean"); // contributed by ConfigForScanning context.getBean(uncapitalize(ComponentForScanning.class.getSimpleName())); context.getBean(uncapitalize(Jsr330NamedForScanning.class.getSimpleName())); Map<String, Object> beans = context.getBeansWithAnnotation(Configuration.class); assertEquals(1, beans.size()); } @Test public void registerAndRefresh() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(Config.class, NameConfig.class); context.refresh(); context.getBean("testBean"); context.getBean("name"); Map<String, Object> beans = context.getBeansWithAnnotation(Configuration.class); assertEquals(2, beans.size()); } @Test public void getBeansWithAnnotation() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(Config.class, NameConfig.class, UntypedFactoryBean.class); context.refresh(); context.getBean("testBean"); context.getBean("name"); Map<String, Object> beans = context.getBeansWithAnnotation(Configuration.class); assertEquals(2, beans.size()); } @Test public void getBeanByType() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class); TestBean testBean = context.getBean(TestBean.class); assertNotNull("getBean() should not return null", testBean); assertThat(testBean.name, equalTo("foo")); } /** * Tests that Configuration classes are registered according to convention * @see org.springframework.beans.factory.support.DefaultBeanNameGenerator#generateBeanName */ @Test public void defaultConfigClassBeanNameIsGeneratedProperly() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class); // attempt to retrieve the instance by its generated bean name Config configObject = (Config) context.getBean("annotationConfigApplicationContextTests.Config"); assertNotNull(configObject); } /** * Tests that specifying @Configuration(value="foo") results in registering * the configuration class with bean name 'foo'. */ @Test public void explicitConfigClassBeanNameIsRespected() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigWithCustomName.class); // attempt to retrieve the instance by its specified name ConfigWithCustomName configObject = (ConfigWithCustomName) context.getBean("customConfigBeanName"); assertNotNull(configObject); } @Test public void getBeanByTypeRaisesNoSuchBeanDefinitionException() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class); // attempt to retrieve a bean that does not exist Class<?> targetType = java.util.regex.Pattern.class; try { Object bean = context.getBean(targetType); fail("should have thrown NoSuchBeanDefinitionException, instead got: " + bean); } catch (NoSuchBeanDefinitionException ex) { assertThat(ex.getMessage(), containsString( format("No unique bean of type [%s] is defined", targetType.getName()))); } } @SuppressWarnings("unchecked") @Test public void getBeanByTypeAmbiguityRaisesException() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TwoTestBeanConfig.class); try { context.getBean(TestBean.class); } catch (RuntimeException ex) { assertThat(ex.getMessage(), allOf( containsString("No unique bean of type [" + TestBean.class.getName() + "] is defined"), containsString("tb1"), containsString("tb2") ) ); } } @Test public void autowiringIsEnabledByDefault() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AutowiredConfig.class); assertThat(context.getBean(TestBean.class).name, equalTo("foo")); } @Test public void nullReturningBeanPostProcessor() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(AutowiredConfig.class); context.getBeanFactory().addBeanPostProcessor(new BeanPostProcessor() { public Object postProcessBeforeInitialization(Object bean, String beanName) { return (bean instanceof TestBean ? null : bean); } public Object postProcessAfterInitialization(Object bean, String beanName) { return bean; } }); context.getBeanFactory().addBeanPostProcessor(new BeanPostProcessor() { public Object postProcessBeforeInitialization(Object bean, String beanName) { bean.getClass().getName(); return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) { bean.getClass().getName(); return bean; } }); context.refresh(); } @Configuration static class Config { @Bean public TestBean testBean() { TestBean testBean = new TestBean(); testBean.name = "foo"; return testBean; } } @Configuration("customConfigBeanName") static class ConfigWithCustomName { @Bean public TestBean testBean() { return new TestBean(); } } static class ConfigMissingAnnotation { @Bean public TestBean testBean() { return new TestBean(); } } @Configuration static class TwoTestBeanConfig { @Bean TestBean tb1() { return new TestBean(); } @Bean TestBean tb2() { return new TestBean(); } } @Configuration static class NameConfig { @Bean String name() { return "foo"; } } @Configuration @Import(NameConfig.class) static class AutowiredConfig { @Autowired String autowiredName; @Bean TestBean testBean() { TestBean testBean = new TestBean(); testBean.name = autowiredName; return testBean; } } static class UntypedFactoryBean implements FactoryBean { public Object getObject() { return null; } public Class getObjectType() { return null; } public boolean isSingleton() { return false; } } } class TestBean { String name; @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; TestBean other = (TestBean) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } }