提交 f2e4ad23 编写于 作者: J Juergen Hoeller

ComponentScan annotation allows for registering beans with lazy initialization

Issue: SPR-10459
上级 ef51d4db
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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.
......@@ -163,6 +163,14 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo
(beanDefinitionDefaults != null ? beanDefinitionDefaults : new BeanDefinitionDefaults());
}
/**
* Return the defaults to use for detected beans (never {@code null}).
* @since 4.1
*/
public BeanDefinitionDefaults getBeanDefinitionDefaults() {
return this.beanDefinitionDefaults;
}
/**
* Set the name-matching patterns for determining autowire candidates.
* @param autowireCandidatePatterns the patterns to match against
......
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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.
......@@ -132,6 +132,13 @@ public @interface ComponentScan {
*/
Filter[] excludeFilters() default {};
/**
* Specify whether scanned beans should be registered for lazy initialization.
* <p>Default is {@code false}; switch this to {@code true} when desired.
* @since 4.1
*/
boolean lazyInit() default false;
/**
* Declares the type filter to be used as an {@linkplain ComponentScan#includeFilters()
......
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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.
......@@ -106,6 +106,11 @@ class ComponentScanAnnotationParser {
}
}
boolean lazyInit = componentScan.getBoolean("lazyInit");
if (lazyInit) {
scanner.getBeanDefinitionDefaults().setLazyInit(true);
}
List<String> basePackages = new ArrayList<String>();
for (String pkg : componentScan.getStringArray("value")) {
if (StringUtils.hasText(pkg)) {
......
......@@ -23,7 +23,17 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.HashSet;
import example.scannable.CustomComponent;
import example.scannable.CustomStereotype;
import example.scannable.DefaultNamedComponent;
import example.scannable.FooService;
import example.scannable.MessageBean;
import example.scannable.ScopedProxyTestBean;
import example.scannable_implicitbasepackage.ComponentScanAnnotatedConfigWithImplicitBasePackage;
import example.scannable_scoped.CustomScopeAnnotationBean;
import example.scannable_scoped.MyScope;
import org.junit.Test;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.CustomAutowireConfigurer;
import org.springframework.beans.factory.config.BeanDefinition;
......@@ -36,16 +46,6 @@ import org.springframework.context.support.GenericApplicationContext;
import org.springframework.tests.context.SimpleMapScope;
import org.springframework.util.SerializationTestUtils;
import example.scannable.CustomComponent;
import example.scannable.CustomStereotype;
import example.scannable.DefaultNamedComponent;
import example.scannable.FooService;
import example.scannable.MessageBean;
import example.scannable.ScopedProxyTestBean;
import example.scannable_implicitbasepackage.ComponentScanAnnotatedConfigWithImplicitBasePackage;
import example.scannable_scoped.CustomScopeAnnotationBean;
import example.scannable_scoped.MyScope;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*;
......@@ -116,10 +116,10 @@ public class ComponentScanAnnotationIntegrationTests {
ctx.getBean(ComposedAnnotationConfig.class);
ctx.getBean(SimpleComponent.class);
assertThat("config class bean not found",
ctx.containsBeanDefinition("componentScanAnnotationIntegrationTests.ComposedAnnotationConfig"), is(true));
assertThat("@ComponentScan annotated @Configuration class registered directly against "
+ "AnnotationConfigApplicationContext did not trigger component scanning as expected",
ctx.containsBean("simpleComponent"), is(true));
ctx.containsBeanDefinition("componentScanAnnotationIntegrationTests.ComposedAnnotationConfig"), is(true));
assertThat("@ComponentScan annotated @Configuration class registered directly against " +
"AnnotationConfigApplicationContext did not trigger component scanning as expected",
ctx.containsBean("simpleComponent"), is(true));
}
@Test
......@@ -159,7 +159,8 @@ public class ComponentScanAnnotationIntegrationTests {
@Test
public void withCustomTypeFilter() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ComponentScanWithCustomTypeFilter.class);
KustomAnnotationAutowiredBean testBean = ctx.getBean(KustomAnnotationAutowiredBean.class);
assertFalse(ctx.getDefaultListableBeanFactory().containsSingleton("kustomBean"));
KustomAnnotationAutowiredBean testBean = ctx.getBean("kustomBean", KustomAnnotationAutowiredBean.class);
assertThat(testBean.getDependency(), notNullValue());
}
......@@ -294,7 +295,8 @@ class MyScopeMetadataResolver extends AnnotationScopeMetadataResolver {
useDefaultFilters=false,
includeFilters=@Filter(type=FilterType.CUSTOM, value=ComponentScanParserTests.CustomTypeFilter.class),
// exclude this class from scanning since it's in the scanned package
excludeFilters=@Filter(type=FilterType.ASSIGNABLE_TYPE, value=ComponentScanWithCustomTypeFilter.class))
excludeFilters=@Filter(type=FilterType.ASSIGNABLE_TYPE, value=ComponentScanWithCustomTypeFilter.class),
lazyInit = true)
class ComponentScanWithCustomTypeFilter {
@Bean
@SuppressWarnings({ "rawtypes", "serial", "unchecked" })
......
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2014 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.
......@@ -17,6 +17,7 @@
package org.springframework.context.annotation;
import org.junit.Test;
import org.springframework.beans.factory.support.DefaultBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.core.type.filter.TypeFilter;
......@@ -29,6 +30,7 @@ import org.springframework.core.type.filter.TypeFilter;
* @see ComponentScanAnnotationIntegrationTests
*/
public class ComponentScanAnnotationTests {
@Test
public void noop() {
// no-op; the @ComponentScan-annotated MyConfig class below simply excercises
......@@ -36,7 +38,9 @@ public class ComponentScanAnnotationTests {
}
}
@interface MyAnnotation { }
@interface MyAnnotation {
}
@Configuration
@ComponentScan(
......@@ -44,18 +48,19 @@ public class ComponentScanAnnotationTests {
nameGenerator = DefaultBeanNameGenerator.class,
scopedProxy = ScopedProxyMode.NO,
scopeResolver = AnnotationScopeMetadataResolver.class,
useDefaultFilters = false,
resourcePattern = "**/*custom.class",
useDefaultFilters = false,
includeFilters = {
@Filter(type = FilterType.ANNOTATION, value = MyAnnotation.class)
},
excludeFilters = {
@Filter(type = FilterType.CUSTOM, value = TypeFilter.class)
}
},
lazyInit = true
)
class MyConfig {
}
@ComponentScan(basePackageClasses=example.scannable.NamedComponent.class)
class SimpleConfig { }
\ No newline at end of file
class SimpleConfig {
}
......@@ -21,7 +21,10 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import example.profilescan.ProfileAnnotatedComponent;
import example.scannable.AutowiredQualifierFooService;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
......@@ -29,9 +32,7 @@ import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import example.profilescan.ProfileAnnotatedComponent;
import example.scannable.AutowiredQualifierFooService;
import org.springframework.stereotype.Component;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
......@@ -134,13 +135,13 @@ public class ComponentScanParserTests {
* Intentionally spelling "custom" with a "k" since there are numerous
* classes in this package named *Custom*.
*/
@Component("kustomBean")
public static class KustomAnnotationAutowiredBean {
@Autowired
@CustomAnnotation
private KustomAnnotationDependencyBean dependency;
public KustomAnnotationDependencyBean getDependency() {
return this.dependency;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册