Allow recursive use of @ComponentScan
Prior to this change, @ComponentScan annotations were only processed at the first level of depth. Now, the set of bean definitions resulting from each declaration of @ComponentScan is checked for configuration classes that declare @ComponentScan, and recursion is performed as necessary. Cycles between @ComponentScan declarations are detected as well. See CircularComponentScanException. Issue: SPR-8307
This commit is contained in:
@@ -16,7 +16,9 @@
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import org.springframework.beans.factory.parsing.FailFastProblemReporter;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.core.env.DefaultEnvironment;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||
|
||||
/**
|
||||
@@ -33,7 +35,12 @@ public class AsmCircularImportDetectionTests extends AbstractCircularImportDetec
|
||||
|
||||
@Override
|
||||
protected ConfigurationClassParser newParser() {
|
||||
return new ConfigurationClassParser(new CachingMetadataReaderFactory(), new FailFastProblemReporter(), new DefaultEnvironment());
|
||||
return new ConfigurationClassParser(
|
||||
new CachingMetadataReaderFactory(),
|
||||
new FailFastProblemReporter(),
|
||||
new DefaultEnvironment(),
|
||||
new DefaultResourceLoader(),
|
||||
new DefaultListableBeanFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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 org.hamcrest.CoreMatchers.sameInstance;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.componentscan.cycle.left.LeftConfig;
|
||||
import org.springframework.context.annotation.componentscan.level1.Level1Config;
|
||||
import org.springframework.context.annotation.componentscan.level2.Level2Config;
|
||||
import org.springframework.context.annotation.componentscan.level3.Level3Component;
|
||||
|
||||
/**
|
||||
* Tests ensuring that configuration clasess marked with @ComponentScan
|
||||
* may be processed recursively
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
public class ComponentScanAnnotationRecursionTests {
|
||||
|
||||
@Test
|
||||
public void recursion() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(Level1Config.class);
|
||||
ctx.refresh();
|
||||
|
||||
// assert that all levels have been detected
|
||||
ctx.getBean(Level1Config.class);
|
||||
ctx.getBean(Level2Config.class);
|
||||
ctx.getBean(Level3Component.class);
|
||||
|
||||
// assert that enhancement is working
|
||||
assertThat(ctx.getBean("level1Bean"), sameInstance(ctx.getBean("level1Bean")));
|
||||
assertThat(ctx.getBean("level2Bean"), sameInstance(ctx.getBean("level2Bean")));
|
||||
}
|
||||
|
||||
@Test(expected=CircularComponentScanException.class)
|
||||
public void cycleDetection() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(LeftConfig.class);
|
||||
ctx.refresh();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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.componentscan.cycle.left;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan("org.springframework.context.annotation.componentscan.cycle.right")
|
||||
public class LeftConfig {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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.componentscan.cycle.right;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan("org.springframework.context.annotation.componentscan.cycle.left")
|
||||
public class RightConfig {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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.componentscan.level1;
|
||||
|
||||
import org.springframework.beans.TestBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan("org.springframework.context.annotation.componentscan.level2")
|
||||
public class Level1Config {
|
||||
@Bean
|
||||
public TestBean level1Bean() {
|
||||
return new TestBean("level1Bean");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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.componentscan.level2;
|
||||
|
||||
import org.springframework.beans.TestBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan("org.springframework.context.annotation.componentscan.level3")
|
||||
public class Level2Config {
|
||||
@Bean
|
||||
public TestBean level2Bean() {
|
||||
return new TestBean("level2Bean");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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.componentscan.level3;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class Level3Component {
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user