From c0e45a4a3bdad47d36c5db4bcff022a1ac892687 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 13 Nov 2012 15:06:54 +0100 Subject: [PATCH] DATACMNS-247 - Improved implementation of RepositoryBeanDefinitionRegistrarSupport. RepositoryBeanDefinitionRegistrarSupport not implements BeanClassLoaderAware and ResourceLoaderAware as Spring 3.2 will regard these callback interfaces and inject the resources. We still default these injected resources upon invocation to be able to run on Spring 3.1 as well. --- ...ositoryBeanDefinitionRegistrarSupport.java | 67 ++++++++++++++++--- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java index b676d2811..5307e18f3 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java @@ -17,25 +17,45 @@ package org.springframework.data.repository.config; import java.lang.annotation.Annotation; +import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.ResourceLoaderAware; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotationMetadata; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; /** * Base class to implement {@link ImportBeanDefinitionRegistrar}s to enable repository * * @author Oliver Gierke */ -public abstract class RepositoryBeanDefinitionRegistrarSupport implements ImportBeanDefinitionRegistrar { +public abstract class RepositoryBeanDefinitionRegistrarSupport implements ImportBeanDefinitionRegistrar, + BeanClassLoaderAware, ResourceLoaderAware { - // see SPR-9568 - private final ResourceLoader resourceLoader = new DefaultResourceLoader(); + private ResourceLoader resourceLoader; + private ClassLoader beanClassLoader; + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(java.lang.ClassLoader) + */ + public void setBeanClassLoader(ClassLoader classLoader) { + this.beanClassLoader = classLoader; + } + + /* + * (non-Javadoc) + * @see org.springframework.context.ResourceLoaderAware#setResourceLoader(org.springframework.core.io.ResourceLoader) + */ + public void setResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } /* * (non-Javadoc) @@ -51,6 +71,8 @@ public abstract class RepositoryBeanDefinitionRegistrarSupport implements Import return; } + defaultExternalResources(registry); + AnnotationRepositoryConfigurationSource configuration = new AnnotationRepositoryConfigurationSource( annotationMetadata, getAnnotation()); @@ -58,7 +80,7 @@ public abstract class RepositoryBeanDefinitionRegistrarSupport implements Import extension.registerBeansForRoot(registry, configuration); RepositoryBeanNameGenerator generator = new RepositoryBeanNameGenerator(); - generator.setBeanClassLoader(getBeanClassLoader(registry)); + generator.setBeanClassLoader(beanClassLoader); for (RepositoryConfiguration repositoryConfiguration : extension .getRepositoryConfigurations(configuration, resourceLoader)) { @@ -73,13 +95,40 @@ public abstract class RepositoryBeanDefinitionRegistrarSupport implements Import } } - private ClassLoader getBeanClassLoader(BeanDefinitionRegistry registry) { + /** + * Workaround the lack of injectability of external resources into {@link ImportBeanDefinitionRegistrar}s in the + * Spring 3.1 timeline. We populate {@link #beanClassLoader} and default the {@link #resourceLoader} in case they + * haven't been set until a call to this method. + * + * @param registry must not be {@literal null}. + * @see SPR-9568 + */ + private void defaultExternalResources(BeanDefinitionRegistry registry) { - if (registry instanceof ConfigurableListableBeanFactory) { - return ((ConfigurableListableBeanFactory) registry).getBeanClassLoader(); + if (beanClassLoader == null) { + this.beanClassLoader = getBeanClassLoader(registry); } - return resourceLoader.getClassLoader(); + if (resourceLoader == null) { + this.resourceLoader = new DefaultResourceLoader(this.beanClassLoader); + } + } + + /** + * Returns the bean class loader contained in the given registry if it is a {@link ConfigurableBeanFactory}. Falls + * back to the {@link ResourceLoader}'s {@link ClassLoader} or the global default one if that one is {@literal null} + * in turn. + * + * @param registry must not be {@literal null}. + * @return + */ + private ClassLoader getBeanClassLoader(BeanDefinitionRegistry registry) { + + if (registry instanceof ConfigurableBeanFactory) { + return ((ConfigurableBeanFactory) registry).getBeanClassLoader(); + } + + return resourceLoader == null ? ClassUtils.getDefaultClassLoader() : resourceLoader.getClassLoader(); } /**