/* * Copyright 2002-2008 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 junit.framework.TestCase; import org.aspectj.lang.annotation.Aspect; import org.springframework.beans.TestBean; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.StaticListableBeanFactory; import org.springframework.context.MessageSource; import org.springframework.context.annotation2.NamedStubDao2; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.core.type.filter.AssignableTypeFilter; import org.springframework.stereotype.Component; /** * @author Mark Fisher * @author Juergen Hoeller */ public class ClassPathBeanDefinitionScannerTests extends TestCase { private static final String BASE_PACKAGE = ClassPathBeanDefinitionScannerTests.class.getPackage().getName(); public void testSimpleScanWithDefaultFiltersAndPostProcessors() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); int beanCount = scanner.scan(BASE_PACKAGE); assertEquals(13, beanCount); assertTrue(context.containsBean("serviceInvocationCounter")); assertTrue(context.containsBean("fooServiceImpl")); assertTrue(context.containsBean("stubFooDao")); assertTrue(context.containsBean("myNamedComponent")); assertTrue(context.containsBean("myNamedDao")); assertTrue(context.containsBean("thoreau")); assertTrue(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } public void testDoubleScan() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); int beanCount = scanner.scan(BASE_PACKAGE); assertEquals(13, beanCount); scanner.scan(BASE_PACKAGE); assertTrue(context.containsBean("serviceInvocationCounter")); assertTrue(context.containsBean("fooServiceImpl")); assertTrue(context.containsBean("stubFooDao")); assertTrue(context.containsBean("myNamedComponent")); assertTrue(context.containsBean("myNamedDao")); assertTrue(context.containsBean("thoreau")); } public void testSimpleScanWithDefaultFiltersAndNoPostProcessors() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); scanner.setIncludeAnnotationConfig(false); int beanCount = scanner.scan(BASE_PACKAGE); assertEquals(9, beanCount); assertTrue(context.containsBean("serviceInvocationCounter")); assertTrue(context.containsBean("fooServiceImpl")); assertTrue(context.containsBean("stubFooDao")); assertTrue(context.containsBean("myNamedComponent")); assertTrue(context.containsBean("myNamedDao")); } public void testSimpleScanWithDefaultFiltersAndOverridingBean() { GenericApplicationContext context = new GenericApplicationContext(); context.registerBeanDefinition("stubFooDao", new RootBeanDefinition(TestBean.class)); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); scanner.setIncludeAnnotationConfig(false); // should not fail! scanner.scan(BASE_PACKAGE); } public void testSimpleScanWithDefaultFiltersAndDefaultBeanNameClash() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); scanner.setIncludeAnnotationConfig(false); try { scanner.scan("org.springframework.context.annotation3"); scanner.scan(BASE_PACKAGE); fail("Should have thrown IllegalStateException"); } catch (IllegalStateException ex) { // expected assertTrue(ex.getMessage().indexOf("stubFooDao") != -1); assertTrue(ex.getMessage().indexOf(StubFooDao.class.getName()) != -1); } } public void testSimpleScanWithDefaultFiltersAndOverriddenEqualNamedBean() { GenericApplicationContext context = new GenericApplicationContext(); context.registerBeanDefinition("myNamedDao", new RootBeanDefinition(NamedStubDao.class)); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); scanner.setIncludeAnnotationConfig(false); int beanCount = scanner.scan(BASE_PACKAGE); assertEquals(8, beanCount); assertEquals(9, context.getBeanDefinitionCount()); assertTrue(context.containsBean("serviceInvocationCounter")); assertTrue(context.containsBean("fooServiceImpl")); assertTrue(context.containsBean("stubFooDao")); assertTrue(context.containsBean("myNamedComponent")); assertTrue(context.containsBean("myNamedDao")); } public void testSimpleScanWithDefaultFiltersAndOverriddenCompatibleNamedBean() { GenericApplicationContext context = new GenericApplicationContext(); RootBeanDefinition bd = new RootBeanDefinition(NamedStubDao.class); bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); context.registerBeanDefinition("myNamedDao", bd); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); scanner.setIncludeAnnotationConfig(false); int beanCount = scanner.scan(BASE_PACKAGE); assertEquals(8, beanCount); assertEquals(9, context.getBeanDefinitionCount()); assertTrue(context.containsBean("serviceInvocationCounter")); assertTrue(context.containsBean("fooServiceImpl")); assertTrue(context.containsBean("stubFooDao")); assertTrue(context.containsBean("myNamedComponent")); assertTrue(context.containsBean("myNamedDao")); } public void testSimpleScanWithDefaultFiltersAndSameBeanTwice() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); scanner.setIncludeAnnotationConfig(false); // should not fail! scanner.scan(BASE_PACKAGE); scanner.scan(BASE_PACKAGE); } public void testSimpleScanWithDefaultFiltersAndSpecifiedBeanNameClash() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); scanner.setIncludeAnnotationConfig(false); try { scanner.scan("org.springframework.context.annotation2"); scanner.scan(BASE_PACKAGE); fail("Must have thrown IllegalStateException"); } catch (IllegalStateException expected) { assertTrue(expected.getMessage().contains("myNamedDao")); assertTrue(expected.getMessage().contains(NamedStubDao.class.getName())); assertTrue(expected.getMessage().contains(NamedStubDao2.class.getName())); } } public void testCustomIncludeFilterWithoutDefaultsButIncludingPostProcessors() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, false); scanner.addIncludeFilter(new AnnotationTypeFilter(CustomComponent.class)); int beanCount = scanner.scan(BASE_PACKAGE); assertEquals(5, beanCount); assertTrue(context.containsBean("messageBean")); assertTrue(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } public void testCustomIncludeFilterWithoutDefaultsAndNoPostProcessors() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, false); scanner.addIncludeFilter(new AnnotationTypeFilter(CustomComponent.class)); int beanCount = scanner.scan(BASE_PACKAGE); assertEquals(5, beanCount); assertTrue(context.containsBean("messageBean")); assertFalse(context.containsBean("serviceInvocationCounter")); assertFalse(context.containsBean("fooServiceImpl")); assertFalse(context.containsBean("stubFooDao")); assertFalse(context.containsBean("myNamedComponent")); assertFalse(context.containsBean("myNamedDao")); assertTrue(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } public void testCustomIncludeFilterAndDefaults() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, true); scanner.addIncludeFilter(new AnnotationTypeFilter(CustomComponent.class)); int beanCount = scanner.scan(BASE_PACKAGE); assertEquals(14, beanCount); assertTrue(context.containsBean("messageBean")); assertTrue(context.containsBean("serviceInvocationCounter")); assertTrue(context.containsBean("fooServiceImpl")); assertTrue(context.containsBean("stubFooDao")); assertTrue(context.containsBean("myNamedComponent")); assertTrue(context.containsBean("myNamedDao")); assertTrue(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } public void testCustomAnnotationExcludeFilterAndDefaults() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, true); scanner.addExcludeFilter(new AnnotationTypeFilter(Aspect.class)); int beanCount = scanner.scan(BASE_PACKAGE); assertEquals(12, beanCount); assertFalse(context.containsBean("serviceInvocationCounter")); assertTrue(context.containsBean("fooServiceImpl")); assertTrue(context.containsBean("stubFooDao")); assertTrue(context.containsBean("myNamedComponent")); assertTrue(context.containsBean("myNamedDao")); assertTrue(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } public void testCustomAssignableTypeExcludeFilterAndDefaults() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, true); scanner.addExcludeFilter(new AssignableTypeFilter(FooService.class)); int beanCount = scanner.scan(BASE_PACKAGE); assertEquals(12, beanCount); assertFalse(context.containsBean("fooServiceImpl")); assertTrue(context.containsBean("serviceInvocationCounter")); assertTrue(context.containsBean("stubFooDao")); assertTrue(context.containsBean("myNamedComponent")); assertTrue(context.containsBean("myNamedDao")); assertTrue(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } public void testCustomAssignableTypeExcludeFilterAndDefaultsWithoutPostProcessors() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, true); scanner.setIncludeAnnotationConfig(false); scanner.addExcludeFilter(new AssignableTypeFilter(FooService.class)); int beanCount = scanner.scan(BASE_PACKAGE); assertEquals(8, beanCount); assertFalse(context.containsBean("fooServiceImpl")); assertTrue(context.containsBean("serviceInvocationCounter")); assertTrue(context.containsBean("stubFooDao")); assertTrue(context.containsBean("myNamedComponent")); assertTrue(context.containsBean("myNamedDao")); assertFalse(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); assertFalse(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); assertFalse(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } public void testMultipleCustomExcludeFiltersAndDefaults() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, true); scanner.addExcludeFilter(new AssignableTypeFilter(FooService.class)); scanner.addExcludeFilter(new AnnotationTypeFilter(Aspect.class)); int beanCount = scanner.scan(BASE_PACKAGE); assertEquals(11, beanCount); assertFalse(context.containsBean("fooServiceImpl")); assertFalse(context.containsBean("serviceInvocationCounter")); assertTrue(context.containsBean("stubFooDao")); assertTrue(context.containsBean("myNamedComponent")); assertTrue(context.containsBean("myNamedDao")); assertTrue(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } public void testCustomBeanNameGenerator() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); scanner.setBeanNameGenerator(new TestBeanNameGenerator()); int beanCount = scanner.scan(BASE_PACKAGE); assertEquals(13, beanCount); assertFalse(context.containsBean("fooServiceImpl")); assertTrue(context.containsBean("fooService")); assertTrue(context.containsBean("serviceInvocationCounter")); assertTrue(context.containsBean("stubFooDao")); assertTrue(context.containsBean("myNamedComponent")); assertTrue(context.containsBean("myNamedDao")); assertTrue(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } public void testMultipleBasePackagesWithDefaultsOnly() { GenericApplicationContext singlePackageContext = new GenericApplicationContext(); ClassPathBeanDefinitionScanner singlePackageScanner = new ClassPathBeanDefinitionScanner(singlePackageContext); GenericApplicationContext multiPackageContext = new GenericApplicationContext(); ClassPathBeanDefinitionScanner multiPackageScanner = new ClassPathBeanDefinitionScanner(multiPackageContext); int singlePackageBeanCount = singlePackageScanner.scan(BASE_PACKAGE); assertEquals(13, singlePackageBeanCount); int multiPackageBeanCount = multiPackageScanner.scan( BASE_PACKAGE, "org.springframework.dao.annotation"); assertTrue(multiPackageBeanCount > singlePackageBeanCount); } public void testMultipleScanCalls() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); int beanCount = scanner.scan(BASE_PACKAGE); assertEquals(13, beanCount); assertEquals(beanCount, context.getBeanDefinitionCount()); int addedBeanCount = scanner.scan("org.springframework.aop.aspectj.annotation"); assertEquals(beanCount + addedBeanCount, context.getBeanDefinitionCount()); } public void testBeanAutowiredWithAnnotationConfigEnabled() { GenericApplicationContext context = new GenericApplicationContext(); context.registerBeanDefinition("myBf", new RootBeanDefinition(StaticListableBeanFactory.class)); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); scanner.setBeanNameGenerator(new TestBeanNameGenerator()); int beanCount = scanner.scan(BASE_PACKAGE); assertEquals(13, beanCount); context.refresh(); FooServiceImpl fooService = (FooServiceImpl) context.getBean("fooService"); StaticListableBeanFactory myBf = (StaticListableBeanFactory) context.getBean("myBf"); MessageSource ms = (MessageSource) context.getBean("messageSource"); assertTrue(fooService.isInitCalled()); assertEquals("bar", fooService.foo(123)); assertSame(context.getDefaultListableBeanFactory(), fooService.beanFactory); assertEquals(2, fooService.listableBeanFactory.size()); assertSame(context.getDefaultListableBeanFactory(), fooService.listableBeanFactory.get(0)); assertSame(myBf, fooService.listableBeanFactory.get(1)); assertSame(context, fooService.resourceLoader); assertSame(context, fooService.resourcePatternResolver); assertSame(context, fooService.eventPublisher); assertSame(ms, fooService.messageSource); assertSame(context, fooService.context); assertEquals(1, fooService.configurableContext.length); assertSame(context, fooService.configurableContext[0]); assertSame(context, fooService.genericContext); } public void testBeanNotAutowiredWithAnnotationConfigDisabled() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); scanner.setIncludeAnnotationConfig(false); scanner.setBeanNameGenerator(new TestBeanNameGenerator()); int beanCount = scanner.scan(BASE_PACKAGE); assertEquals(9, beanCount); context.refresh(); FooService fooService = (FooService) context.getBean("fooService"); assertFalse(fooService.isInitCalled()); try { fooService.foo(123); fail("NullPointerException expected; fooDao must not have been set"); } catch (NullPointerException expected) { } } public void testAutowireCandidatePatternMatches() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); scanner.setIncludeAnnotationConfig(true); scanner.setBeanNameGenerator(new TestBeanNameGenerator()); scanner.setAutowireCandidatePatterns(new String[] { "*FooDao" }); scanner.scan(BASE_PACKAGE); context.refresh(); FooService fooService = (FooService) context.getBean("fooService"); assertEquals("bar", fooService.foo(123)); } public void testAutowireCandidatePatternDoesNotMatch() { GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); scanner.setIncludeAnnotationConfig(true); scanner.setBeanNameGenerator(new TestBeanNameGenerator()); scanner.setAutowireCandidatePatterns(new String[] { "*NoSuchDao" }); scanner.scan(BASE_PACKAGE); try { context.refresh(); fail("BeanCreationException expected; fooDao should not have been an autowire-candidate"); } catch (BeanCreationException expected) { assertTrue(expected.getMostSpecificCause() instanceof NoSuchBeanDefinitionException); } } private static class TestBeanNameGenerator extends AnnotationBeanNameGenerator { @Override public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { String beanName = super.generateBeanName(definition, registry); return beanName.replace("Impl", ""); } } @Component("toBeIgnored") public class NonStaticInnerClass { } }