Browse Source

DATACMNS-952 - Switched from component scanning to SpringFactoriesLoader for internal extension points.

Both the configuration code looking up Spring Data specific Jackson modules as well as the code detecting whether we have multiple Spring Data modules on the classpath used component scanning. That can have quite significant impact on startup times.

This commit replaces the classpath scanning with the use of SpringFactoriesLoader that now requires modules that want to extend the behavior of Spring Data's web configuration or indicate a repository implementation being present by shipping a file called META-INF/spring.factories. Spring Data relies on the following keys:

- org.springframework.data.web.config.SpringDataJacksonModules - list the Spring configuration classes that will expose additional Jackson modules that are supposed to be registered for Spring Data's Jackson web support
- org.springframework.data.repository.core.support.RepositoryFactorySupport - list the Spring Data repository factory implementation class that implements repository support for your module. The general detection and configuration mechanism for user repositories is not affected by this. Currently Spring Data only uses the pure number of different entries for that key to switch into strict configuration mode in case we find more than one entry.
pull/183/merge
Oliver Gierke 9 years ago
parent
commit
76d1995b37
  1. 16
      src/main/java/org/springframework/data/repository/config/RepositoryConfigurationDelegate.java
  2. 15
      src/main/java/org/springframework/data/web/config/EnableSpringDataWebSupport.java
  3. 5
      src/main/java/org/springframework/data/web/config/SpringDataJacksonConfiguration.java
  4. 27
      src/main/java/org/springframework/data/web/config/SpringDataJacksonModules.java
  5. 41
      src/main/java/org/springframework/data/web/config/SpringDataWebConfigurationMixin.java
  6. 1
      src/main/resources/META-INF/spring.factories
  7. 3
      src/test/java/org/springframework/data/web/config/SampleMixin.java
  8. 1
      src/test/resources/META-INF/spring.factories

16
src/main/java/org/springframework/data/repository/config/RepositoryConfigurationDelegate.java

@ -25,12 +25,11 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition; @@ -25,12 +25,11 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.env.Environment;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import org.springframework.util.Assert;
@ -48,7 +47,6 @@ public class RepositoryConfigurationDelegate { @@ -48,7 +47,6 @@ public class RepositoryConfigurationDelegate {
private static final String REPOSITORY_REGISTRATION = "Spring Data {} - Registering repository: {} - Interface: {} - Factory: {}";
private static final String MULTIPLE_MODULES = "Multiple Spring Data modules found, entering strict repository configuration mode!";
private static final String MODULE_DETECTION_PACKAGE = "org.springframework.data.**.repository.support";
static final String FACTORY_BEAN_OBJECT_TYPE = "factoryBeanObjectType";
@ -160,17 +158,13 @@ public class RepositoryConfigurationDelegate { @@ -160,17 +158,13 @@ public class RepositoryConfigurationDelegate {
*/
private boolean multipleStoresDetected() {
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.setEnvironment(environment);
scanner.setResourceLoader(resourceLoader);
scanner.addIncludeFilter(new AssignableTypeFilter(RepositoryFactorySupport.class));
if (scanner.findCandidateComponents(MODULE_DETECTION_PACKAGE).size() > 1) {
boolean multipleModulesFound = SpringFactoriesLoader
.loadFactoryNames(RepositoryFactorySupport.class, resourceLoader.getClassLoader()).size() > 1;
if (multipleModulesFound) {
LOGGER.info(MULTIPLE_MODULES);
return true;
}
return false;
return multipleModulesFound;
}
}

15
src/main/java/org/springframework/data/web/config/EnableSpringDataWebSupport.java

@ -23,16 +23,14 @@ import java.lang.annotation.Target; @@ -23,16 +23,14 @@ import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.querydsl.QueryDslUtils;
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
import org.springframework.util.ClassUtils;
@ -124,15 +122,8 @@ public @interface EnableSpringDataWebSupport { @@ -124,15 +122,8 @@ public @interface EnableSpringDataWebSupport {
: SpringDataWebConfiguration.class.getName());
if (JACKSON_PRESENT) {
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.setEnvironment(environment);
provider.setResourceLoader(resourceLoader);
provider.addIncludeFilter(new AnnotationTypeFilter(SpringDataWebConfigurationMixin.class));
for (BeanDefinition definition : provider.findCandidateComponents("org.springframework.data")) {
imports.add(definition.getBeanClassName());
}
imports.addAll(
SpringFactoriesLoader.loadFactoryNames(SpringDataJacksonModules.class, resourceLoader.getClassLoader()));
}
return imports.toArray(new String[imports.size()]);

5
src/main/java/org/springframework/data/web/config/SpringDataJacksonConfiguration.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2014-2015 the original author or authors.
* Copyright 2014-2016 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.
@ -23,8 +23,7 @@ import org.springframework.data.geo.GeoModule; @@ -23,8 +23,7 @@ import org.springframework.data.geo.GeoModule;
*
* @author Oliver Gierke
*/
@SpringDataWebConfigurationMixin
public class SpringDataJacksonConfiguration {
public class SpringDataJacksonConfiguration implements SpringDataJacksonModules {
@Bean
public GeoModule jacksonGeoModule() {

27
src/main/java/org/springframework/data/web/config/SpringDataJacksonModules.java

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
/*
* Copyright 2016 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.data.web.config;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Marker interface to describe configuration classes that ship Jackson modules that are supposed to be added to the
* Jackson {@link ObjectMapper} configured for {@link EnableSpringDataWebSupport}.
*
* @author Oliver Gierke
* @since 1.13
*/
public interface SpringDataJacksonModules {}

41
src/main/java/org/springframework/data/web/config/SpringDataWebConfigurationMixin.java

@ -1,41 +0,0 @@ @@ -1,41 +0,0 @@
/*
* Copyright 2015 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.data.web.config;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.web.config.EnableSpringDataWebSupport.SpringDataWebConfigurationImportSelector;
/**
* Annotation to be able to scan for additional Spring Data configuration classes to contribute to the web integration.
*
* @author Oliver Gierke
* @since 1.10
* @soundtrack Selah Sue - This World (Selah Sue)
* @see SpringDataJacksonConfiguration
* @see SpringDataWebConfigurationImportSelector
*/
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE })
public @interface SpringDataWebConfigurationMixin {
}

1
src/main/resources/META-INF/spring.factories

@ -0,0 +1 @@ @@ -0,0 +1 @@
org.springframework.data.web.config.SpringDataJacksonModules=org.springframework.data.web.config.SpringDataJacksonConfiguration

3
src/test/java/org/springframework/data/web/config/SampleMixin.java

@ -20,8 +20,7 @@ import org.springframework.context.annotation.Bean; @@ -20,8 +20,7 @@ import org.springframework.context.annotation.Bean;
/**
* @author Oliver Gierke
*/
@SpringDataWebConfigurationMixin
public class SampleMixin {
public class SampleMixin implements SpringDataJacksonModules {
@Bean
String sampleBean() {

1
src/test/resources/META-INF/spring.factories

@ -0,0 +1 @@ @@ -0,0 +1 @@
org.springframework.data.web.config.SpringDataJacksonModules=org.springframework.data.web.config.SampleMixin
Loading…
Cancel
Save