Merge branch '1.2.x'

pull/3245/head
Phillip Webb 10 years ago
commit 79179a7773

@ -16,8 +16,8 @@
package org.springframework.boot.orm.jpa; package org.springframework.boot.orm.jpa;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;
@ -25,6 +25,7 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
@ -40,6 +41,7 @@ import org.springframework.util.ObjectUtils;
* {@link ImportBeanDefinitionRegistrar} used by {@link EntityScan}. * {@link ImportBeanDefinitionRegistrar} used by {@link EntityScan}.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Oliver Gierke
*/ */
class EntityScanRegistrar implements ImportBeanDefinitionRegistrar { class EntityScanRegistrar implements ImportBeanDefinitionRegistrar {
@ -48,31 +50,25 @@ class EntityScanRegistrar implements ImportBeanDefinitionRegistrar {
@Override @Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) { BeanDefinitionRegistry registry) {
Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
if (!registry.containsBeanDefinition(BEAN_NAME)) { if (!registry.containsBeanDefinition(BEAN_NAME)) {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition(); addEntityScanBeanPostProcessor(registry, packagesToScan);
beanDefinition.setBeanClass(EntityScanBeanPostProcessor.class); }
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue( else {
getPackagesToScan(importingClassMetadata)); updateEntityScanBeanPostProcessor(registry, packagesToScan);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// We don't need this one to be post processed otherwise it can cause a
// cascade of bean instantiation that we would rather avoid.
beanDefinition.setSynthetic(true);
registry.registerBeanDefinition(BEAN_NAME, beanDefinition);
} }
} }
private String[] getPackagesToScan(AnnotationMetadata metadata) { private Set<String> getPackagesToScan(AnnotationMetadata metadata) {
AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata
.getAnnotationAttributes(EntityScan.class.getName())); .getAnnotationAttributes(EntityScan.class.getName()));
String[] value = attributes.getStringArray("value"); String[] value = attributes.getStringArray("value");
String[] basePackages = attributes.getStringArray("basePackages"); String[] basePackages = attributes.getStringArray("basePackages");
Class<?>[] basePackageClasses = attributes.getClassArray("basePackageClasses"); Class<?>[] basePackageClasses = attributes.getClassArray("basePackageClasses");
if (!ObjectUtils.isEmpty(value)) { if (!ObjectUtils.isEmpty(value)) {
Assert.state(ObjectUtils.isEmpty(basePackages), Assert.state(ObjectUtils.isEmpty(basePackages),
"@EntityScan basePackages and value attributes are mutually exclusive"); "@EntityScan basePackages and value attributes are mutually exclusive");
} }
Set<String> packagesToScan = new LinkedHashSet<String>(); Set<String> packagesToScan = new LinkedHashSet<String>();
packagesToScan.addAll(Arrays.asList(value)); packagesToScan.addAll(Arrays.asList(value));
packagesToScan.addAll(Arrays.asList(basePackages)); packagesToScan.addAll(Arrays.asList(basePackages));
@ -80,10 +76,38 @@ class EntityScanRegistrar implements ImportBeanDefinitionRegistrar {
packagesToScan.add(ClassUtils.getPackageName(basePackageClass)); packagesToScan.add(ClassUtils.getPackageName(basePackageClass));
} }
if (packagesToScan.isEmpty()) { if (packagesToScan.isEmpty()) {
return new String[] { ClassUtils.getPackageName(metadata.getClassName()) }; return Collections.singleton(ClassUtils.getPackageName(metadata
.getClassName()));
} }
return new ArrayList<String>(packagesToScan).toArray(new String[packagesToScan return packagesToScan;
.size()]); }
private void addEntityScanBeanPostProcessor(BeanDefinitionRegistry registry,
Set<String> packagesToScan) {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(EntityScanBeanPostProcessor.class);
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(
toArray(packagesToScan));
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// We don't need this one to be post processed otherwise it can cause a
// cascade of bean instantiation that we would rather avoid.
beanDefinition.setSynthetic(true);
registry.registerBeanDefinition(BEAN_NAME, beanDefinition);
}
private void updateEntityScanBeanPostProcessor(BeanDefinitionRegistry registry,
Set<String> packagesToScan) {
BeanDefinition definition = registry.getBeanDefinition(BEAN_NAME);
ValueHolder constructorArguments = definition.getConstructorArgumentValues()
.getGenericArgumentValue(String[].class);
Set<String> mergedPackages = new LinkedHashSet<String>();
mergedPackages.addAll(Arrays.asList((String[]) constructorArguments.getValue()));
mergedPackages.addAll(packagesToScan);
constructorArguments.setValue(toArray(mergedPackages));
}
private String[] toArray(Set<String> set) {
return set.toArray(new String[set.size()]);
} }
/** /**

@ -109,6 +109,13 @@ public class EntityScanTests {
assertSetPackagesToScan("com.mycorp.entity"); assertSetPackagesToScan("com.mycorp.entity");
} }
@Test
public void considersMultipleEntityScanAnnotations() {
this.context = new AnnotationConfigApplicationContext(MultiScanFirst.class,
MultiScanSecond.class);
assertSetPackagesToScan("foo", "bar");
}
private void assertSetPackagesToScan(String... expected) { private void assertSetPackagesToScan(String... expected) {
String[] actual = this.context.getBean( String[] actual = this.context.getBean(
TestLocalContainerEntityManagerFactoryBean.class).getPackagesToScan(); TestLocalContainerEntityManagerFactoryBean.class).getPackagesToScan();
@ -185,6 +192,16 @@ public class EntityScanTests {
} }
} }
@EntityScan(basePackages = "foo")
static class MultiScanFirst extends BaseConfig {
}
@EntityScan(basePackages = "bar")
static class MultiScanSecond extends BaseConfig {
}
private static class TestLocalContainerEntityManagerFactoryBean extends private static class TestLocalContainerEntityManagerFactoryBean extends
LocalContainerEntityManagerFactoryBean { LocalContainerEntityManagerFactoryBean {

Loading…
Cancel
Save