diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java index ff4f6149c0..73d84f8c3f 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java @@ -16,8 +16,6 @@ package org.springframework.context.annotation; -import static org.springframework.context.annotation.MetadataUtils.attributesFor; - import java.io.IOException; import java.util.Arrays; import java.util.Collections; @@ -31,13 +29,19 @@ import java.util.Set; import java.util.Stack; import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.Aware; +import org.springframework.beans.factory.BeanClassLoaderAware; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.parsing.Location; import org.springframework.beans.factory.parsing.Problem; import org.springframework.beans.factory.parsing.ProblemReporter; import org.springframework.beans.factory.support.BeanDefinitionReader; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanNameGenerator; +import org.springframework.context.ResourceLoaderAware; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.Environment; @@ -52,6 +56,8 @@ import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.AssignableTypeFilter; import org.springframework.util.StringUtils; +import static org.springframework.context.annotation.MetadataUtils.*; + /** * Parses a {@link Configuration} class definition, populating a collection of * {@link ConfigurationClass} objects (parsing a single Configuration class may result in @@ -318,6 +324,7 @@ class ConfigurationClassParser { // the candidate class is an ImportBeanDefinitionRegistrar -> delegate to it to register additional bean definitions try { ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(Class.forName(candidate), ImportBeanDefinitionRegistrar.class); + invokeAwareMethods(registrar); registrar.registerBeanDefinitions(importingClassMetadata, registry); } catch (ClassNotFoundException ex) { @@ -334,6 +341,29 @@ class ConfigurationClassParser { } } + /** + * Invoke {@link ResourceLoaderAware}, {@link BeanClassLoaderAware} and + * {@link BeanFactoryAware} contracts if implemented by the given {@code registrar}. + */ + private void invokeAwareMethods(ImportBeanDefinitionRegistrar registrar) { + if (registrar instanceof Aware) { + if (registrar instanceof ResourceLoaderAware) { + ((ResourceLoaderAware) registrar).setResourceLoader(resourceLoader); + } + if (registrar instanceof BeanClassLoaderAware) { + ClassLoader classLoader = + registry instanceof ConfigurableBeanFactory ? + ((ConfigurableBeanFactory) registry).getBeanClassLoader() : + resourceLoader.getClassLoader(); + ((BeanClassLoaderAware) registrar).setBeanClassLoader(classLoader); + } + if (registrar instanceof BeanFactoryAware && registry instanceof BeanFactory) { + ((BeanFactoryAware) registrar).setBeanFactory((BeanFactory) registry); + } + } + } + + /** * Validate each {@link ConfigurationClass} object. * @see ConfigurationClass#validate @@ -356,7 +386,6 @@ class ConfigurationClassParser { return this.importStack; } - interface ImportRegistry { String getImportingClassFor(String importedClass); diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ImportBeanDefinitionRegistrar.java b/spring-context/src/main/java/org/springframework/context/annotation/ImportBeanDefinitionRegistrar.java index 21f29813a8..da58779fd8 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ImportBeanDefinitionRegistrar.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ImportBeanDefinitionRegistrar.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -29,6 +29,15 @@ import org.springframework.core.type.AnnotationMetadata; * may be provided to the @{@link Import} annotation (or may also be returned from an * {@code ImportSelector}). * + *
An {@link ImportBeanDefinitionRegistrar} may implement any of the following + * {@link org.springframework.beans.factory.Aware Aware} interfaces, and their respective + * methods will be called prior to {@link #registerBeanDefinitions}: + *
See implementations and associated unit tests for usage examples. * * @author Chris Beams diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ImportBeanDefinitionRegistrarTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ImportBeanDefinitionRegistrarTests.java new file mode 100644 index 0000000000..be69b30cdc --- /dev/null +++ b/spring-context/src/test/java/org/springframework/context/annotation/ImportBeanDefinitionRegistrarTests.java @@ -0,0 +1,93 @@ +/* + * Copyright 2002-2012 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.*; +import static org.junit.Assert.*; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.junit.Test; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanClassLoaderAware; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.MessageSource; +import org.springframework.context.ResourceLoaderAware; +import org.springframework.core.io.ResourceLoader; +import org.springframework.core.type.AnnotationMetadata; + +/** + * Integration tests for {@link ImportBeanDefinitionRegistrar}. + * + * @author Oliver Gierke + * @author Chris Beams + */ +public class ImportBeanDefinitionRegistrarTests { + + @Test + public void shouldInvokeAwareMethodsInImportBeanDefinitionRegistrar() { + + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class); + context.getBean(MessageSource.class); + + assertThat(SampleRegistrar.beanFactory, is((BeanFactory) context.getBeanFactory())); + assertThat(SampleRegistrar.classLoader, is(context.getBeanFactory().getBeanClassLoader())); + assertThat(SampleRegistrar.resourceLoader, is(notNullValue())); + } + + @Sample + @Configuration + static class Config { + + } + + @Target(ElementType.TYPE) + @Retention(RetentionPolicy.RUNTIME) + @Import(SampleRegistrar.class) + public static @interface Sample { + + } + + static class SampleRegistrar implements ImportBeanDefinitionRegistrar, BeanClassLoaderAware, ResourceLoaderAware, + BeanFactoryAware { + + static ClassLoader classLoader; + static ResourceLoader resourceLoader; + static BeanFactory beanFactory; + + public void setBeanClassLoader(ClassLoader classLoader) { + SampleRegistrar.classLoader = classLoader; + } + + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + SampleRegistrar.beanFactory = beanFactory; + } + + public void setResourceLoader(ResourceLoader resourceLoader) { + SampleRegistrar.resourceLoader = resourceLoader; + } + + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + } + } +}