Skip to content

Commit e06ad72

Browse files
committed
Avoid reflection in RepositoryRestMvcConfiguration.
We now completely avoid reflection in RepositoryRestMvcConfiguration by delaying all bean lookups that were previously declared through autowired fields. Fixes #2057.
1 parent eeee271 commit e06ad72

File tree

1 file changed

+59
-40
lines changed

1 file changed

+59
-40
lines changed

spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.java

Lines changed: 59 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import org.springframework.beans.factory.BeanFactoryUtils;
3030
import org.springframework.beans.factory.ObjectFactory;
3131
import org.springframework.beans.factory.ObjectProvider;
32-
import org.springframework.beans.factory.annotation.Autowired;
3332
import org.springframework.beans.factory.annotation.Qualifier;
3433
import org.springframework.context.ApplicationContext;
3534
import org.springframework.context.annotation.Bean;
@@ -88,6 +87,7 @@
8887
import org.springframework.data.rest.webmvc.support.RepositoryEntityLinks;
8988
import org.springframework.data.util.AnnotatedTypeScanner;
9089
import org.springframework.data.util.Lazy;
90+
import org.springframework.data.util.StreamUtils;
9191
import org.springframework.data.web.HateoasPageableHandlerMethodArgumentResolver;
9292
import org.springframework.data.web.HateoasSortHandlerMethodArgumentResolver;
9393
import org.springframework.data.web.config.EnableSpringDataWebSupport;
@@ -155,47 +155,43 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon
155155
private static final boolean IS_JPA_AVAILABLE = ClassUtils.isPresent("javax.persistence.EntityManager",
156156
RepositoryRestMvcConfiguration.class.getClassLoader());
157157

158-
@Autowired ApplicationContext applicationContext;
158+
private final ApplicationContext applicationContext;
159+
private final ConversionService defaultConversionService;
159160

160-
@Autowired(required = false) List<EntityLookup<?>> lookups = Collections.emptyList();
161-
162-
@Autowired List<HttpMessageConverter<?>> defaultMessageConverters;
163-
164-
ObjectProvider<LinkRelationProvider> relProvider;
165-
ObjectProvider<CurieProvider> curieProvider;
166-
ObjectProvider<HalConfiguration> halConfiguration;
167-
ObjectProvider<ObjectMapper> objectMapper;
168-
ObjectProvider<RepresentationModelProcessorInvoker> invoker;
169-
ObjectProvider<MessageResolver> resolver;
170-
ObjectProvider<GeoModule> geoModule;
171-
172-
ConversionService defaultConversionService;
161+
private final ObjectProvider<LinkRelationProvider> relProvider;
162+
private final ObjectProvider<CurieProvider> curieProvider;
163+
private final ObjectProvider<HalConfiguration> halConfiguration;
164+
private final ObjectProvider<ObjectMapper> objectMapper;
165+
private final ObjectProvider<RepresentationModelProcessorInvoker> invoker;
166+
private final ObjectProvider<MessageResolver> resolver;
167+
private final ObjectProvider<GeoModule> geoModule;
168+
private final ObjectProvider<PathPatternParser> parser;
173169

174170
private final Lazy<ObjectMapper> mapper;
175-
private final ObjectProvider<PathPatternParser> parser;
171+
private final Lazy<? extends List<EntityLookup<?>>> lookups;
172+
private final Lazy<? extends List<HttpMessageConverter<?>>> defaultMessageConverters;
173+
private final Lazy<RepositoryRestConfigurerDelegate> configurerDelegate;
174+
private final Lazy<SelfLinkProvider> selfLinkProvider;
175+
private final Lazy<PersistentEntityResourceHandlerMethodArgumentResolver> persistentEntityArgumentResolver;
176+
private final Lazy<RootResourceInformationHandlerMethodArgumentResolver> repoRequestArgumentResolver;
177+
private final Lazy<BaseUri> baseUri;
178+
private final Lazy<RepositoryResourceMappings> resourceMappings;
179+
private final Lazy<Repositories> repositories;
180+
private final Lazy<ResourceMetadataHandlerMethodArgumentResolver> resourceMetadataHandlerMethodArgumentResolver;
181+
private final Lazy<ExcerptProjector> excerptProjector;
182+
private final Lazy<PersistentEntities> persistentEntities;
183+
private final Lazy<BackendIdHandlerMethodArgumentResolver> backendIdHandlerMethodArgumentResolver;
184+
private final Lazy<Associations> associationLinks;
185+
private final Lazy<EnumTranslator> enumTranslator;
186+
private final Lazy<ServerHttpRequestMethodArgumentResolver> serverHttpRequestMethodArgumentResolver;
187+
private final Lazy<ETagArgumentResolver> eTagArgumentResolver;
188+
private final Lazy<RepositoryInvokerFactory> repositoryInvokerFactory;
189+
private final Lazy<RepositoryRestConfiguration> repositoryRestConfiguration;
190+
private final Lazy<HateoasPageableHandlerMethodArgumentResolver> pageableResolver;
191+
private final Lazy<HateoasSortHandlerMethodArgumentResolver> sortResolver;
176192

177193
private ClassLoader beanClassLoader;
178194

179-
private Lazy<RepositoryRestConfigurerDelegate> configurerDelegate;
180-
private Lazy<SelfLinkProvider> selfLinkProvider;
181-
private Lazy<PersistentEntityResourceHandlerMethodArgumentResolver> persistentEntityArgumentResolver;
182-
private Lazy<RootResourceInformationHandlerMethodArgumentResolver> repoRequestArgumentResolver;
183-
private Lazy<BaseUri> baseUri;
184-
private Lazy<RepositoryResourceMappings> resourceMappings;
185-
private Lazy<Repositories> repositories;
186-
private Lazy<ResourceMetadataHandlerMethodArgumentResolver> resourceMetadataHandlerMethodArgumentResolver;
187-
private Lazy<ExcerptProjector> excerptProjector;
188-
private Lazy<PersistentEntities> persistentEntities;
189-
private Lazy<BackendIdHandlerMethodArgumentResolver> backendIdHandlerMethodArgumentResolver;
190-
private Lazy<Associations> associationLinks;
191-
private Lazy<EnumTranslator> enumTranslator;
192-
private Lazy<ServerHttpRequestMethodArgumentResolver> serverHttpRequestMethodArgumentResolver;
193-
private Lazy<ETagArgumentResolver> eTagArgumentResolver;
194-
private Lazy<RepositoryInvokerFactory> repositoryInvokerFactory;
195-
private Lazy<RepositoryRestConfiguration> repositoryRestConfiguration;
196-
private Lazy<HateoasPageableHandlerMethodArgumentResolver> pageableResolver;
197-
private Lazy<HateoasSortHandlerMethodArgumentResolver> sortResolver;
198-
199195
public RepositoryRestMvcConfiguration( //
200196
ApplicationContext context, //
201197
@Qualifier("mvcConversionService") ObjectFactory<ConversionService> conversionService, //
@@ -210,6 +206,7 @@ public RepositoryRestMvcConfiguration( //
210206

211207
super(context, conversionService);
212208

209+
this.applicationContext = context;
213210
this.relProvider = relProvider;
214211
this.curieProvider = curieProvider;
215212
this.halConfiguration = halConfiguration;
@@ -218,6 +215,7 @@ public RepositoryRestMvcConfiguration( //
218215
this.resolver = resolver;
219216
this.geoModule = geoModule;
220217
this.parser = parser;
218+
this.defaultConversionService = new DefaultFormattingConversionService();
221219

222220
this.mapper = Lazy.of(() -> {
223221

@@ -253,11 +251,10 @@ public RepositoryRestMvcConfiguration( //
253251
this.serverHttpRequestMethodArgumentResolver = Lazy
254252
.of(() -> context.getBean(ServerHttpRequestMethodArgumentResolver.class));
255253
this.eTagArgumentResolver = Lazy.of(() -> context.getBean(ETagArgumentResolver.class));
254+
256255
this.repositoryInvokerFactory = Lazy.of(() -> new UnwrappingRepositoryInvokerFactory(
257256
new DefaultRepositoryInvokerFactory(repositories.get(), defaultConversionService), getEntityLookups()));
258257

259-
this.defaultConversionService = new DefaultFormattingConversionService();
260-
261258
this.configurerDelegate = Lazy.of(() -> {
262259

263260
return new RepositoryRestConfigurerDelegate(context.getBeanProvider(RepositoryRestConfigurer.class)
@@ -268,6 +265,11 @@ public RepositoryRestMvcConfiguration( //
268265
this.repositoryRestConfiguration = Lazy.of(() -> context.getBean(RepositoryRestConfiguration.class));
269266
this.pageableResolver = Lazy.of(() -> context.getBean(HateoasPageableHandlerMethodArgumentResolver.class));
270267
this.sortResolver = Lazy.of(() -> context.getBean(HateoasSortHandlerMethodArgumentResolver.class));
268+
269+
// Resolution via ResolvableType needed to make the wildcard assignment work
270+
271+
this.lookups = beansOfType(context, EntityLookup.class);
272+
this.defaultMessageConverters = beansOfType(context, HttpMessageConverter.class);
271273
}
272274

273275
/*
@@ -747,7 +749,7 @@ public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> excep
747749
ExceptionHandlerExceptionResolver er = new ExceptionHandlerExceptionResolver();
748750
er.setCustomArgumentResolvers(defaultMethodArgumentResolvers(selfLinkProvider.get(),
749751
persistentEntityArgumentResolver.get(), repoRequestArgumentResolver.get()));
750-
er.setMessageConverters(defaultMessageConverters);
752+
er.setMessageConverters(defaultMessageConverters.get());
751753

752754
configurerDelegate.get().configureExceptionHandlerExceptionResolver(er);
753755

@@ -879,7 +881,7 @@ protected List<EntityLookup<?>> getEntityLookups() {
879881

880882
List<EntityLookup<?>> lookups = new ArrayList<>();
881883
lookups.addAll(repositoryRestConfiguration.get().getEntityLookups(repositories.get()));
882-
lookups.addAll(this.lookups);
884+
lookups.addAll(this.lookups.get());
883885

884886
return lookups;
885887
}
@@ -990,6 +992,23 @@ public void addResourceHandlers(ResourceHandlerRegistry registry) {
990992
.forEach(it -> it.customizeResources(registry, repositoryRestConfiguration.get()));
991993
}
992994

995+
/**
996+
* Helper to be able to obtain a {@link List} of generic types. Otherwise the assignment from {@code Foo} to
997+
* {@code Foo<?>} doesn't work.
998+
*
999+
* @param <S>
1000+
* @param context
1001+
* @param type
1002+
* @return
1003+
*/
1004+
@SuppressWarnings("unchecked")
1005+
private static <S> Lazy<List<S>> beansOfType(ApplicationContext context, Class<?> type) {
1006+
1007+
return Lazy.of(() -> (List<S>) context.getBeanProvider(type)
1008+
.orderedStream()
1009+
.collect(StreamUtils.toUnmodifiableList()));
1010+
}
1011+
9931012
private static class ResourceSupportHttpMessageConverter extends TypeConstrainedMappingJackson2HttpMessageConverter
9941013
implements Ordered {
9951014

0 commit comments

Comments
 (0)