diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java b/spring-context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java
index 0c53a93b9e..1fb174bd81 100644
--- a/spring-context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java
+++ b/spring-context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java
@@ -1,5 +1,5 @@
/*
- * 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
diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ComponentScan.java b/spring-context/src/main/java/org/springframework/context/annotation/ComponentScan.java
index 10529a50c7..d855d90d81 100644
--- a/spring-context/src/main/java/org/springframework/context/annotation/ComponentScan.java
+++ b/spring-context/src/main/java/org/springframework/context/annotation/ComponentScan.java
@@ -1,5 +1,5 @@
/*
- * 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.
+ *
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()
diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ComponentScanAnnotationParser.java b/spring-context/src/main/java/org/springframework/context/annotation/ComponentScanAnnotationParser.java
index 559645800a..0f6f9d1a37 100644
--- a/spring-context/src/main/java/org/springframework/context/annotation/ComponentScanAnnotationParser.java
+++ b/spring-context/src/main/java/org/springframework/context/annotation/ComponentScanAnnotationParser.java
@@ -1,5 +1,5 @@
/*
- * 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 basePackages = new ArrayList();
for (String pkg : componentScan.getStringArray("value")) {
if (StringUtils.hasText(pkg)) {
diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanAnnotationIntegrationTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanAnnotationIntegrationTests.java
index b913d281b3..e228b0d758 100644
--- a/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanAnnotationIntegrationTests.java
+++ b/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanAnnotationIntegrationTests.java
@@ -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" })
diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanAnnotationTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanAnnotationTests.java
index f686a69bdc..ec17007cdc 100644
--- a/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanAnnotationTests.java
+++ b/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanAnnotationTests.java
@@ -1,5 +1,5 @@
/*
- * 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 {
+}
diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanParserTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanParserTests.java
index 8b1068b65f..230cf600d3 100644
--- a/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanParserTests.java
+++ b/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanParserTests.java
@@ -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;
}