|
21 | 21 | import java.util.HashMap;
|
22 | 22 | import java.util.List;
|
23 | 23 | import java.util.Map;
|
| 24 | +import java.util.Set; |
| 25 | +import java.util.function.Consumer; |
| 26 | +import java.util.function.Supplier; |
24 | 27 | import java.util.stream.Collectors;
|
25 | 28 |
|
26 | 29 | import org.apache.commons.logging.Log;
|
27 | 30 | import org.apache.commons.logging.LogFactory;
|
28 |
| - |
29 | 31 | import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
30 | 32 | import org.springframework.beans.factory.config.DependencyDescriptor;
|
31 | 33 | import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
|
44 | 46 | import org.springframework.core.log.LogMessage;
|
45 | 47 | import org.springframework.core.metrics.ApplicationStartup;
|
46 | 48 | import org.springframework.core.metrics.StartupStep;
|
| 49 | +import org.springframework.data.domain.ManagedTypes; |
47 | 50 | import org.springframework.data.repository.core.support.RepositoryFactorySupport;
|
| 51 | +import org.springframework.data.util.Lazy; |
| 52 | +import org.springframework.data.util.TypeScanner; |
48 | 53 | import org.springframework.lang.Nullable;
|
49 | 54 | import org.springframework.util.Assert;
|
50 | 55 | import org.springframework.util.StopWatch;
|
| 56 | +import org.springframework.util.StringUtils; |
51 | 57 |
|
52 | 58 | /**
|
53 | 59 | * Delegate for configuration integration to reuse the general way of detecting repositories. Customization is done by
|
@@ -203,9 +209,49 @@ public List<BeanComponentDefinition> registerRepositoriesIn(BeanDefinitionRegist
|
203 | 209 | watch.getLastTaskTimeMillis(), configurations.size(), extension.getModuleName()));
|
204 | 210 | }
|
205 | 211 |
|
| 212 | + registerManagedTypes(registry, extension, |
| 213 | + () -> configurations.stream().flatMap(it -> it.getBasePackages().stream()).collect(Collectors.toSet())); |
206 | 214 | return definitions;
|
207 | 215 | }
|
208 | 216 |
|
| 217 | + protected void registerManagedTypes(BeanDefinitionRegistry registry, RepositoryConfigurationExtension extension, |
| 218 | + Supplier<Set<String>> basePackages) { |
| 219 | + |
| 220 | + String beanName = String.format("%s.managed-types", extension.getModulePrefix()); |
| 221 | + if (!registry.isBeanNameInUse(beanName)) { |
| 222 | + |
| 223 | + // this needs to be lazy or we'd resolve types to early maybe |
| 224 | + Supplier<Set<Class<?>>> args = new Supplier<Set<Class<?>>>() { |
| 225 | + |
| 226 | + @Override |
| 227 | + public Set<Class<?>> get() { |
| 228 | + |
| 229 | + Set<String> packagesToScan = basePackages.get(); |
| 230 | + |
| 231 | + ApplicationStartup startup = getStartup(registry); |
| 232 | + StartupStep typeScan = startup.start("spring.data.type.scanning"); |
| 233 | + typeScan.tag("dataModule", extension.getModuleName()); |
| 234 | + typeScan.tag("basePackages", () -> StringUtils.collectionToCommaDelimitedString(packagesToScan)); |
| 235 | + |
| 236 | + Set<Class<?>> types = TypeScanner.typeScanner(resourceLoader) // |
| 237 | + .scanPackages(packagesToScan) // |
| 238 | + .forTypesAnnotatedWith(extension.getIdentifyingAnnotations()) // |
| 239 | + .collectAsSet(); |
| 240 | + |
| 241 | + //TODO: should the set include the repo domain types |
| 242 | + |
| 243 | + typeScan.tag("type.count", Integer.toString(types.size())); |
| 244 | + typeScan.end(); |
| 245 | + |
| 246 | + return types; |
| 247 | + } |
| 248 | + }; |
| 249 | + |
| 250 | + registry.registerBeanDefinition(beanName, BeanDefinitionBuilder.rootBeanDefinition(ManagedTypesBean.class) |
| 251 | + .addConstructorArgValue(args).getBeanDefinition()); |
| 252 | + } |
| 253 | + } |
| 254 | + |
209 | 255 | /**
|
210 | 256 | * Registers a {@link LazyRepositoryInjectionPointResolver} over the default
|
211 | 257 | * {@link ContextAnnotationAutowireCandidateResolver} to make injection points of lazy repositories lazy, too. Will
|
@@ -332,4 +378,30 @@ protected boolean isLazy(DependencyDescriptor descriptor) {
|
332 | 378 | return lazyInit;
|
333 | 379 | }
|
334 | 380 | }
|
| 381 | + |
| 382 | + /** |
| 383 | + * Lazy evalutating ManagedTypes implementation using a supplier to avoid eager class instantiation. This type is |
| 384 | + * intended to be rewritten during AOT processing. |
| 385 | + * |
| 386 | + * @author Christoph Strobl |
| 387 | + * @since 3.0 |
| 388 | + */ |
| 389 | + static class ManagedTypesBean implements ManagedTypes { |
| 390 | + |
| 391 | + private Lazy<Set<Class<?>>> types; |
| 392 | + |
| 393 | + ManagedTypesBean(Supplier<Set<Class<?>>> types) { |
| 394 | + this.types = Lazy.of(types); |
| 395 | + } |
| 396 | + |
| 397 | + @Override |
| 398 | + public List<Class<?>> toList() { |
| 399 | + return new ArrayList<>(types.get()); |
| 400 | + } |
| 401 | + |
| 402 | + @Override |
| 403 | + public void forEach(Consumer<Class<?>> action) { |
| 404 | + types.get().forEach(action); |
| 405 | + } |
| 406 | + } |
335 | 407 | }
|
0 commit comments