Browse Source

Polishing.

Move off TypeReference for known and loaded classes for easier handling. Introduce configuration for enabled and include/exclude filters. Refactor configuration to functional style.

Original Pull Request: #3318
pull/3357/head
Mark Paluch 4 months ago committed by Christoph Strobl
parent
commit
8eec269324
No known key found for this signature in database
GPG Key ID: E6054036D0C37A4B
  1. 37
      src/main/java/org/springframework/data/aot/AotContext.java
  2. 52
      src/main/java/org/springframework/data/aot/AotMappingContext.java
  3. 36
      src/main/java/org/springframework/data/aot/AotTypeConfiguration.java
  4. 127
      src/main/java/org/springframework/data/aot/DefaultAotContext.java
  5. 11
      src/main/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessor.java
  6. 6
      src/main/java/org/springframework/data/mapping/context/ReflectionFallbackPersistentPropertyAccessorFactory.java
  7. 12
      src/main/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiator.java
  8. 7
      src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java
  9. 14
      src/main/java/org/springframework/data/mapping/model/EntityInstantiatorSource.java
  10. 3
      src/main/java/org/springframework/data/mapping/model/EntityInstantiators.java
  11. 12
      src/main/java/org/springframework/data/repository/config/DefaultAotRepositoryContext.java
  12. 37
      src/main/java/org/springframework/data/repository/config/RepositoryRegistrationAotContribution.java
  13. 4
      src/main/java/org/springframework/data/repository/config/RepositoryRegistrationAotProcessor.java
  14. 214
      src/test/java/org/springframework/data/aot/AotContextUnitTests.java
  15. 10
      src/test/java/org/springframework/data/repository/aot/generate/DummyModuleAotRepositoryContext.java

37
src/main/java/org/springframework/data/aot/AotContext.java

@ -22,7 +22,6 @@ import java.util.Locale;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Predicate;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.TypeReference; import org.springframework.aot.hint.TypeReference;
@ -230,18 +229,31 @@ public interface AotContext extends EnvironmentCapable {
*/ */
IntrospectedBeanDefinition introspectBeanDefinition(String beanName); IntrospectedBeanDefinition introspectBeanDefinition(String beanName);
InstantiationCreator instantiationCreator(TypeReference typeReference); /**
* Obtain a {@link AotTypeConfiguration} for the given {@link ResolvableType} to customize the AOT processing for the
default AotTypeConfiguration typeConfiguration(ResolvableType resolvableType) { * given type.
return typeConfiguration(resolvableType.toClass()); *
} * @param resolvableType the resolvable type to configure.
* @param configurationConsumer configuration consumer function.
default AotTypeConfiguration typeConfiguration(Class<?> type) { */
return typeConfiguration(TypeReference.of(type)); default void typeConfiguration(ResolvableType resolvableType, Consumer<AotTypeConfiguration> configurationConsumer) {
typeConfiguration(resolvableType.toClass(), configurationConsumer);
} }
AotTypeConfiguration typeConfiguration(TypeReference typeReference); /**
* Obtain a {@link AotTypeConfiguration} for the given {@link ResolvableType} to customize the AOT processing for the
* given type.
*
* @param type the type to configure.
* @param configurationConsumer configuration consumer function.
*/
void typeConfiguration(Class<?> type, Consumer<AotTypeConfiguration> configurationConsumer);
/**
* Return all type configurations registered with this {@link AotContext}.
*
* @return all type configurations registered with this {@link AotContext}.
*/
Collection<AotTypeConfiguration> typeConfigurations(); Collection<AotTypeConfiguration> typeConfigurations();
/** /**
@ -358,9 +370,4 @@ public interface AotContext extends EnvironmentCapable {
Class<?> resolveType(); Class<?> resolveType();
} }
interface InstantiationCreator {
boolean isAvailable();
void create();
}
} }

52
src/main/java/org/springframework/data/aot/AotMappingContext.java

@ -24,8 +24,8 @@ import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
import org.springframework.data.mapping.model.BasicPersistentEntity; import org.springframework.data.mapping.model.BasicPersistentEntity;
import org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory; import org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory;
import org.springframework.data.mapping.model.EntityInstantiator; import org.springframework.data.mapping.model.EntityInstantiator;
import org.springframework.data.mapping.model.EntityInstantiatorSource;
import org.springframework.data.mapping.model.EntityInstantiators; import org.springframework.data.mapping.model.EntityInstantiators;
import org.springframework.data.mapping.model.PersistentEntityClassInitializer;
import org.springframework.data.mapping.model.Property; import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.SimpleTypeHolder; import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.repository.aot.generate.RepositoryContributor; import org.springframework.data.repository.aot.generate.RepositoryContributor;
@ -37,48 +37,53 @@ import org.springframework.data.util.TypeInformation;
* @author Mark Paluch * @author Mark Paluch
* @since 4.0 * @since 4.0
*/ */
class AotMappingContext extends // TODO: hide this one and delegate to other component - can we use the class AotMappingContext extends
// AotContext for it? AbstractMappingContext<BasicPersistentEntity<?, AotMappingContext.AotPersistentProperty>, AotMappingContext.AotPersistentProperty> {
AbstractMappingContext<BasicPersistentEntity<?, AotMappingContext.BasicPersistentProperty>, AotMappingContext.BasicPersistentProperty> {
private static final Log logger = LogFactory.getLog(AotMappingContext.class); private static final Log logger = LogFactory.getLog(AotMappingContext.class);
private final EntityInstantiators instantiators = new EntityInstantiators(); private final EntityInstantiators instantiators = new EntityInstantiators();
private final ClassGeneratingPropertyAccessorFactory propertyAccessorFactory = new ClassGeneratingPropertyAccessorFactory(); private final AotAccessorFactory propertyAccessorFactory = new AotAccessorFactory();
/** /**
* Contribute entity instantiators and property accessors for the given {@link PersistentEntity} that are captured * Contribute entity instantiators and property accessors for the given {@link PersistentEntity} that are captured
* through Spring's {@code CglibClassHandler}. Otherwise, this is a no-op if contributions are not ran through * through Spring's {@code CglibClassHandler}. Otherwise, this is a no-op if contributions are not ran through
* {@code CglibClassHandler}. * {@code CglibClassHandler}.
* *
* @param entity * @param entityType
*/ */
public void contribute(PersistentEntity<?, ?> entity) { public void contribute(Class<?> entityType) {
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
if (instantiator instanceof PersistentEntityClassInitializer pec) { BasicPersistentEntity<?, AotPersistentProperty> entity = getPersistentEntity(entityType);
pec.initialize(entity);
if (entity != null) {
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
if (instantiator instanceof EntityInstantiatorSource source) {
source.getInstantiatorFor(entity);
}
propertyAccessorFactory.initialize(entity);
} }
propertyAccessorFactory.initialize(entity);
} }
// TODO: can we extract some util for this using only type
@Override @Override
protected <T> BasicPersistentEntity<?, BasicPersistentProperty> createPersistentEntity( protected <T> BasicPersistentEntity<?, AotPersistentProperty> createPersistentEntity(
TypeInformation<T> typeInformation) { TypeInformation<T> typeInformation) {
logger.debug("I hate gradle: create persistent entity for type: " + typeInformation); logger.debug("I hate gradle: create persistent entity for type: " + typeInformation);
return new BasicPersistentEntity<>(typeInformation); return new BasicPersistentEntity<>(typeInformation);
} }
@Override @Override
protected BasicPersistentProperty createPersistentProperty(Property property, protected AotPersistentProperty createPersistentProperty(Property property,
BasicPersistentEntity<?, BasicPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) { BasicPersistentEntity<?, AotPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
logger.info("creating property: " + property.getName()); logger.info("creating property: " + property.getName());
return new BasicPersistentProperty(property, owner, simpleTypeHolder); return new AotPersistentProperty(property, owner, simpleTypeHolder);
} }
static class BasicPersistentProperty extends AnnotationBasedPersistentProperty<BasicPersistentProperty> { static class AotPersistentProperty extends AnnotationBasedPersistentProperty<AotPersistentProperty> {
public BasicPersistentProperty(Property property, PersistentEntity<?, BasicPersistentProperty> owner, public AotPersistentProperty(Property property, PersistentEntity<?, AotPersistentProperty> owner,
SimpleTypeHolder simpleTypeHolder) { SimpleTypeHolder simpleTypeHolder) {
super(property, owner, simpleTypeHolder); super(property, owner, simpleTypeHolder);
} }
@ -89,15 +94,22 @@ class AotMappingContext extends // TODO: hide this one and delegate to other com
} }
@Override @Override
protected Association<BasicPersistentProperty> createAssociation() { protected Association<AotPersistentProperty> createAssociation() {
return new Association<>(this, null); return new Association<>(this, null);
} }
@Override @Override
public Association<BasicPersistentProperty> getRequiredAssociation() { public Association<AotPersistentProperty> getAssociation() {
return new Association<>(this, null); return new Association<>(this, null);
} }
} }
static class AotAccessorFactory extends ClassGeneratingPropertyAccessorFactory {
public void initialize(PersistentEntity<?, ?> entity) {
potentiallyCreateAndRegisterPersistentPropertyAccessorClass(entity);
}
}
} }

36
src/main/java/org/springframework/data/aot/AotTypeConfiguration.java

@ -39,10 +39,10 @@ public interface AotTypeConfiguration {
AotTypeConfiguration forReflectiveAccess(MemberCategory... categories); AotTypeConfiguration forReflectiveAccess(MemberCategory... categories);
AotTypeConfiguration generateEntityInstantiator(); AotTypeConfiguration contributeAccessors();
// TODO: ? should this be a global condition for the entire configuration or do we need it for certain aspects ? // TODO: ? should this be a global condition for the entire configuration or do we need it for certain aspects ?
AotTypeConfiguration conditional(Predicate<TypeReference> filter); AotTypeConfiguration filter(Predicate<Class<?>> filter);
default AotTypeConfiguration usedAsProjectionInterface() { default AotTypeConfiguration usedAsProjectionInterface() {
return proxyInterface(TargetAware.class, SpringProxy.class, DecoratingProxy.class); return proxyInterface(TargetAware.class, SpringProxy.class, DecoratingProxy.class);
@ -69,42 +69,12 @@ public interface AotTypeConfiguration {
AotTypeConfiguration proxyInterface(List<TypeReference> proxyInterfaces); AotTypeConfiguration proxyInterface(List<TypeReference> proxyInterfaces);
default AotTypeConfiguration proxyInterface(TypeReference... proxyInterfaces) {
return proxyInterface(List.of(proxyInterfaces));
}
default AotTypeConfiguration proxyInterface(Class<?>... proxyInterfaces) { default AotTypeConfiguration proxyInterface(Class<?>... proxyInterfaces) {
return proxyInterface(Stream.of(proxyInterfaces).map(TypeReference::of).toList()); return proxyInterface(Stream.of(proxyInterfaces).map(TypeReference::of).toList());
} }
AotTypeConfiguration forQuerydsl(); AotTypeConfiguration forQuerydsl();
void contribute(GenerationContext generationContext); void contribute(Environment environment, GenerationContext generationContext);
static Predicate<TypeReference> userConfiguredCondition(Environment environment) {
return new Predicate<TypeReference>() {
private final List<String> allowedAccessorTypes = environment.getProperty("spring.data.aot.generate.accessor",
List.class, List.of());
@Override
@SuppressWarnings("unchecked")
public boolean test(TypeReference typeReference) {
if (!allowedAccessorTypes.isEmpty()) {
if (allowedAccessorTypes.contains("none") || allowedAccessorTypes.contains("false")
|| allowedAccessorTypes.contains("off")) {
return false;
}
if (!allowedAccessorTypes.contains(typeReference.getName())) {
return false;
}
}
return true;
}
};
}
} }

127
src/main/java/org/springframework/data/aot/DefaultAotContext.java

@ -40,13 +40,14 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.data.aot.AotMappingContext.BasicPersistentProperty;
import org.springframework.data.mapping.model.BasicPersistentEntity;
import org.springframework.data.util.Lazy;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.core.env.Environment;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.util.QTypeContributor; import org.springframework.data.util.QTypeContributor;
import org.springframework.data.util.TypeContributor; import org.springframework.data.util.TypeContributor;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/** /**
* Default {@link AotContext} implementation. * Default {@link AotContext} implementation.
@ -56,17 +57,16 @@ import org.springframework.util.ClassUtils;
*/ */
class DefaultAotContext implements AotContext { class DefaultAotContext implements AotContext {
private final AotMappingContext mappingContext = new AotMappingContext(); private final AotMappingContext mappingContext = new AotMappingContext();;
private final ConfigurableListableBeanFactory factory; private final ConfigurableListableBeanFactory factory;
// TODO: should we reuse the config or potentially have multiple ones with different settings - somehow targets the // TODO: should we reuse the config or potentially have multiple ones with different settings - somehow targets the
// filtering issue // filtering issue
private final Map<TypeReference, AotTypeConfiguration> typeConfigurations = new HashMap<>(); private final Map<Class<?>, AotTypeConfiguration> typeConfigurations = new HashMap<>();
private final Environment environment;
private final Environment environment;
public DefaultAotContext(BeanFactory beanFactory, Environment environment) { public DefaultAotContext(BeanFactory beanFactory, Environment environment) {
factory = beanFactory instanceof ConfigurableListableBeanFactory cbf ? cbf this.factory = beanFactory instanceof ConfigurableListableBeanFactory cbf ? cbf
: new DefaultListableBeanFactory(beanFactory); : new DefaultListableBeanFactory(beanFactory);
this.environment = environment; this.environment = environment;
} }
@ -92,13 +92,8 @@ class DefaultAotContext implements AotContext {
} }
@Override @Override
public InstantiationCreator instantiationCreator(TypeReference typeReference) { public void typeConfiguration(Class<?> type, Consumer<AotTypeConfiguration> configurationConsumer) {
return new DefaultInstantiationCreator(introspectType(typeReference.getName())); configurationConsumer.accept(typeConfigurations.computeIfAbsent(type, it -> new ContextualTypeConfiguration(type)));
}
@Override
public AotTypeConfiguration typeConfiguration(TypeReference typeReference) {
return typeConfigurations.computeIfAbsent(typeReference, it -> new ContextualTypeConfiguration(typeReference));
} }
@Override @Override
@ -145,29 +140,6 @@ class DefaultAotContext implements AotContext {
} }
} }
class DefaultInstantiationCreator implements InstantiationCreator {
Lazy<BasicPersistentEntity<?, BasicPersistentProperty>> entity;
public DefaultInstantiationCreator(TypeIntrospector typeIntrospector) {
this.entity = Lazy.of(() -> mappingContext.getPersistentEntity(typeIntrospector.resolveRequiredType()));
}
@Override
public boolean isAvailable() {
return entity.getNullable() != null;
}
@Override
public void create() {
BasicPersistentEntity<?, BasicPersistentProperty> persistentEntity = entity.getNullable();
if (persistentEntity != null) {
mappingContext.contribute(persistentEntity);
}
}
}
class DefaultIntrospectedBeanDefinition implements IntrospectedBeanDefinition { class DefaultIntrospectedBeanDefinition implements IntrospectedBeanDefinition {
private final String beanName; private final String beanName;
@ -210,15 +182,15 @@ class DefaultAotContext implements AotContext {
class ContextualTypeConfiguration implements AotTypeConfiguration { class ContextualTypeConfiguration implements AotTypeConfiguration {
private final TypeReference type; private final Class<?> type;
private boolean forDataBinding = false; private boolean forDataBinding = false;
private final Set<MemberCategory> categories = new HashSet<>(5); private final Set<MemberCategory> categories = new HashSet<>(5);
private boolean generateEntityInstantiator = false; private boolean contributeAccessors = false;
private boolean forQuerydsl = false; private boolean forQuerydsl = false;
private final List<List<TypeReference>> proxies = new ArrayList<>(); private final List<List<TypeReference>> proxies = new ArrayList<>();
private Predicate<TypeReference> filter; private Predicate<Class<?>> filter;
ContextualTypeConfiguration(TypeReference type) { ContextualTypeConfiguration(Class<?> type) {
this.type = type; this.type = type;
} }
@ -235,8 +207,8 @@ class DefaultAotContext implements AotContext {
} }
@Override @Override
public AotTypeConfiguration generateEntityInstantiator() { public AotTypeConfiguration contributeAccessors() {
this.generateEntityInstantiator = true; this.contributeAccessors = true;
return this; return this;
} }
@ -253,14 +225,14 @@ class DefaultAotContext implements AotContext {
} }
@Override @Override
public AotTypeConfiguration conditional(Predicate<TypeReference> filter) { public AotTypeConfiguration filter(Predicate<Class<?>> filter) {
this.filter = filter; this.filter = filter;
return this; return this;
} }
@Override @Override
public void contribute(GenerationContext generationContext) { public void contribute(Environment environment, GenerationContext generationContext) {
if (filter != null && !filter.test(this.type)) { if (filter != null && !filter.test(this.type)) {
return; return;
@ -271,43 +243,70 @@ class DefaultAotContext implements AotContext {
categories.toArray(MemberCategory[]::new)); categories.toArray(MemberCategory[]::new));
} }
if (generateEntityInstantiator) { if (contributeAccessors) {
instantiationCreator(type).create();
boolean accessorsEnabled = environment.getProperty("spring.aot.data.accessors.enabled", Boolean.class, true);
String include = environment.getProperty("spring.aot.data.accessors.include", String.class, "");
String exclude = environment.getProperty("spring.aot.data.accessors.exclude", String.class, "");
if (shouldContributeAccessors(type, accessorsEnabled, include, exclude)) {
mappingContext.contribute(type);
}
} }
if (forDataBinding) { if (forDataBinding) {
if (!doIfPresent(resolved -> TypeContributor.contribute(resolved, Set.of(TypeContributor.DATA_NAMESPACE),
generationContext))) { TypeContributor.contribute(type, Set.of(TypeContributor.DATA_NAMESPACE), generationContext);
generationContext.getRuntimeHints().reflection().registerType(type,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS); generationContext.getRuntimeHints().reflection().registerType(type, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
} MemberCategory.INVOKE_DECLARED_METHODS);
} }
if (forQuerydsl) { if (forQuerydsl) {
doIfPresent( QTypeContributor.contributeEntityPath(type, generationContext, factory.getBeanClassLoader());
resolved -> QTypeContributor.contributeEntityPath(resolved, generationContext, resolved.getClassLoader()));
} }
if (!proxies.isEmpty()) { if (!proxies.isEmpty()) {
for (List<TypeReference> proxyInterfaces : proxies) { for (List<TypeReference> proxyInterfaces : proxies) {
generationContext.getRuntimeHints().proxies() generationContext.getRuntimeHints().proxies()
.registerJdkProxy(Stream.concat(Stream.of(type), proxyInterfaces.stream()).toArray(TypeReference[]::new)); .registerJdkProxy(Stream.concat(Stream.of(TypeReference.of(type)), proxyInterfaces.stream())
.toArray(TypeReference[]::new));
} }
} }
} }
private boolean doIfPresent(Consumer<Class<?>> consumer) { static boolean shouldContributeAccessors(Class<?> type, boolean enabled, String include, String exclude) {
if (!ClassUtils.isPresent(type.getName(), type.getClass().getClassLoader())) {
if (!enabled) {
return false; return false;
} }
try {
Class<?> resolved = ClassUtils.forName(type.getName(), type.getClass().getClassLoader()); AntPathMatcher antPathMatcher = new AntPathMatcher(".");
consumer.accept(resolved);
return true; if (StringUtils.hasText(include)) {
} catch (ClassNotFoundException e) {
return false; String[] includes = include.split(",");
for (String includePattern : includes) {
if (antPathMatcher.match(includePattern.trim(), type.getName())) {
return true;
}
}
} }
if (StringUtils.hasText(exclude)) {
String[] excludes = exclude.split(",");
for (String excludePattern : excludes) {
if (antPathMatcher.match(excludePattern.trim(), type.getName())) {
return false;
}
}
}
return true;
} }
} }
} }

11
src/main/java/org/springframework/data/aot/ManagedTypesBeanRegistrationAotProcessor.java

@ -53,8 +53,8 @@ public class ManagedTypesBeanRegistrationAotProcessor implements BeanRegistratio
private final Log logger = LogFactory.getLog(getClass()); private final Log logger = LogFactory.getLog(getClass());
private @Nullable String moduleIdentifier; private @Nullable String moduleIdentifier;
private Lazy<Environment> environment = Lazy.of(StandardEnvironment::new);
private AotContext aotContext; private AotContext aotContext;
private Lazy<Environment> environment = Lazy.of(StandardEnvironment::new);
public void setModuleIdentifier(@Nullable String moduleIdentifier) { public void setModuleIdentifier(@Nullable String moduleIdentifier) {
this.moduleIdentifier = moduleIdentifier; this.moduleIdentifier = moduleIdentifier;
@ -67,7 +67,7 @@ public class ManagedTypesBeanRegistrationAotProcessor implements BeanRegistratio
@Override @Override
public void setEnvironment(Environment environment) { public void setEnvironment(Environment environment) {
this.environment = Lazy.of(() -> environment); this.environment = Lazy.of(environment);
} }
@Override @Override
@ -144,10 +144,9 @@ public class ManagedTypesBeanRegistrationAotProcessor implements BeanRegistratio
Set<String> annotationNamespaces = Collections.singleton(TypeContributor.DATA_NAMESPACE); Set<String> annotationNamespaces = Collections.singleton(TypeContributor.DATA_NAMESPACE);
aotContext.typeConfiguration(type).forDataBinding() // aotContext.typeConfiguration(type, config -> config.forDataBinding() //
.generateEntityInstantiator() // .contributeAccessors() //
.forQuerydsl() // .forQuerydsl().contribute(environment.get(), generationContext));
.contribute(generationContext); //
TypeUtils.resolveUsedAnnotations(type.toClass()).forEach( TypeUtils.resolveUsedAnnotations(type.toClass()).forEach(
annotation -> TypeContributor.contribute(annotation.getType(), annotationNamespaces, generationContext)); annotation -> TypeContributor.contribute(annotation.getType(), annotationNamespaces, generationContext));

6
src/main/java/org/springframework/data/mapping/context/ReflectionFallbackPersistentPropertyAccessorFactory.java

@ -36,13 +36,9 @@ class ReflectionFallbackPersistentPropertyAccessorFactory implements PersistentP
public <T> PersistentPropertyAccessor<T> getPropertyAccessor(PersistentEntity<?, ?> entity, T bean) { public <T> PersistentPropertyAccessor<T> getPropertyAccessor(PersistentEntity<?, ?> entity, T bean) {
if (accessorFactory.isSupported(entity)) { if (accessorFactory.isSupported(entity)) {
PersistentPropertyAccessor<T> propertyAccessor = accessorFactory.getPropertyAccessor(entity, bean); return accessorFactory.getPropertyAccessor(entity, bean);
System.out.println("Accessor Factory: " + propertyAccessor.getClass().getName());
return propertyAccessor;
} }
System.out.println("Fallback Accessor Factory :(");
return BeanWrapperPropertyAccessorFactory.INSTANCE.getPropertyAccessor(entity, bean); return BeanWrapperPropertyAccessorFactory.INSTANCE.getPropertyAccessor(entity, bean);
} }

12
src/main/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiator.java

@ -60,7 +60,7 @@ import org.springframework.util.ClassUtils;
* @author Mark Paluch * @author Mark Paluch
* @since 1.11 * @since 1.11
*/ */
class ClassGeneratingEntityInstantiator implements EntityInstantiator, PersistentEntityClassInitializer { class ClassGeneratingEntityInstantiator implements EntityInstantiator, EntityInstantiatorSource {
private static final Log LOGGER = LogFactory.getLog(ClassGeneratingEntityInstantiator.class); private static final Log LOGGER = LogFactory.getLog(ClassGeneratingEntityInstantiator.class);
@ -87,11 +87,6 @@ class ClassGeneratingEntityInstantiator implements EntityInstantiator, Persisten
this.fallbackToReflectionOnError = fallbackToReflectionOnError; this.fallbackToReflectionOnError = fallbackToReflectionOnError;
} }
@Override
public void initialize(PersistentEntity<?, ?> entity) {
getEntityInstantiator(entity);
}
@Override @Override
public <T, E extends PersistentEntity<? extends T, P>, P extends PersistentProperty<P>> T createInstance(E entity, public <T, E extends PersistentEntity<? extends T, P>, P extends PersistentProperty<P>> T createInstance(E entity,
ParameterValueProvider<P> provider) { ParameterValueProvider<P> provider) {
@ -100,6 +95,11 @@ class ClassGeneratingEntityInstantiator implements EntityInstantiator, Persisten
return instantiator.createInstance(entity, provider); return instantiator.createInstance(entity, provider);
} }
@Override
public EntityInstantiator getInstantiatorFor(PersistentEntity<?, ?> entity) {
return getEntityInstantiator(entity);
}
private <T, E extends PersistentEntity<? extends T, P>, P extends PersistentProperty<P>> EntityInstantiator getEntityInstantiator( private <T, E extends PersistentEntity<? extends T, P>, P extends PersistentProperty<P>> EntityInstantiator getEntityInstantiator(
E entity) { E entity) {

7
src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java

@ -77,7 +77,7 @@ import org.springframework.util.StringUtils;
* @since 1.13 * @since 1.13
*/ */
public class ClassGeneratingPropertyAccessorFactory public class ClassGeneratingPropertyAccessorFactory
implements PersistentPropertyAccessorFactory, PersistentEntityClassInitializer { implements PersistentPropertyAccessorFactory {
// Pooling of parameter arrays to prevent excessive object allocation. // Pooling of parameter arrays to prevent excessive object allocation.
private final ThreadLocal<Object[]> argumentCache = ThreadLocal.withInitial(() -> new Object[1]); private final ThreadLocal<Object[]> argumentCache = ThreadLocal.withInitial(() -> new Object[1]);
@ -89,11 +89,6 @@ public class ClassGeneratingPropertyAccessorFactory
private final ConcurrentLruCache<PersistentProperty<?>, Function<@Nullable Object, @Nullable Object>> wrapperCache = new ConcurrentLruCache<>( private final ConcurrentLruCache<PersistentProperty<?>, Function<@Nullable Object, @Nullable Object>> wrapperCache = new ConcurrentLruCache<>(
256, KotlinValueBoxingAdapter::getWrapper); 256, KotlinValueBoxingAdapter::getWrapper);
@Override
public void initialize(PersistentEntity<?, ?> entity) {
getPropertyAccessorConstructor(entity);
}
@Override @Override
public <T> PersistentPropertyAccessor<T> getPropertyAccessor(PersistentEntity<?, ?> entity, T bean) { public <T> PersistentPropertyAccessor<T> getPropertyAccessor(PersistentEntity<?, ?> entity, T bean) {

14
src/main/java/org/springframework/data/mapping/model/PersistentEntityClassInitializer.java → src/main/java/org/springframework/data/mapping/model/EntityInstantiatorSource.java

@ -18,9 +18,19 @@ package org.springframework.data.mapping.model;
import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentEntity;
/** /**
* Interface declaring a source for {@link EntityInstantiator} objects.
*
* @author Mark Paluch * @author Mark Paluch
* @since 4.0
*/ */
public interface PersistentEntityClassInitializer { @FunctionalInterface
public interface EntityInstantiatorSource {
/**
* Returns an {@link EntityInstantiator} for the given {@link PersistentEntity}.
*
* @return the {@link EntityInstantiator} for the given {@link PersistentEntity}.
*/
EntityInstantiator getInstantiatorFor(PersistentEntity<?, ?> entity);
void initialize(PersistentEntity<?, ?> entity);
} }

3
src/main/java/org/springframework/data/mapping/model/EntityInstantiators.java

@ -31,7 +31,7 @@ import org.springframework.util.Assert;
* @author Mark Paluch * @author Mark Paluch
* @since 2.3 * @since 2.3
*/ */
public class EntityInstantiators { public class EntityInstantiators implements EntityInstantiatorSource {
private final EntityInstantiator fallback; private final EntityInstantiator fallback;
private final Map<Class<?>, EntityInstantiator> customInstantiators; private final Map<Class<?>, EntityInstantiator> customInstantiators;
@ -84,6 +84,7 @@ public class EntityInstantiators {
* @param entity must not be {@literal null}. * @param entity must not be {@literal null}.
* @return will never be {@literal null}. * @return will never be {@literal null}.
*/ */
@Override
public EntityInstantiator getInstantiatorFor(PersistentEntity<?, ?> entity) { public EntityInstantiator getInstantiatorFor(PersistentEntity<?, ?> entity) {
Assert.notNull(entity, "Entity must not be null"); Assert.notNull(entity, "Entity must not be null");

12
src/main/java/org/springframework/data/repository/config/DefaultAotRepositoryContext.java

@ -19,11 +19,10 @@ import java.lang.annotation.Annotation;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.springframework.aot.hint.TypeReference;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.core.annotation.MergedAnnotation; import org.springframework.core.annotation.MergedAnnotation;
@ -151,13 +150,8 @@ class DefaultAotRepositoryContext implements AotRepositoryContext {
} }
@Override @Override
public InstantiationCreator instantiationCreator(TypeReference typeReference) { public void typeConfiguration(Class<?> type, Consumer<AotTypeConfiguration> configurationConsumer) {
return aotContext.instantiationCreator(typeReference); aotContext.typeConfiguration(type, configurationConsumer);
}
@Override
public AotTypeConfiguration typeConfiguration(TypeReference typeReference) {
return aotContext.typeConfiguration(typeReference);
} }
@Override @Override

37
src/main/java/org/springframework/data/repository/config/RepositoryRegistrationAotContribution.java

@ -39,6 +39,9 @@ import org.springframework.beans.factory.aot.BeanRegistrationCode;
import org.springframework.beans.factory.aot.BeanRegistrationCodeFragments; import org.springframework.beans.factory.aot.BeanRegistrationCodeFragments;
import org.springframework.beans.factory.aot.BeanRegistrationCodeFragmentsDecorator; import org.springframework.beans.factory.aot.BeanRegistrationCodeFragmentsDecorator;
import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.DecoratingProxy; import org.springframework.core.DecoratingProxy;
import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.AnnotationUtils;
@ -51,6 +54,7 @@ import org.springframework.data.repository.aot.generate.AotRepositoryBeanDefinit
import org.springframework.data.repository.aot.generate.RepositoryContributor; import org.springframework.data.repository.aot.generate.RepositoryContributor;
import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.support.RepositoryFragment; import org.springframework.data.repository.core.support.RepositoryFragment;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.Predicates; import org.springframework.data.util.Predicates;
import org.springframework.data.util.QTypeContributor; import org.springframework.data.util.QTypeContributor;
import org.springframework.data.util.TypeContributor; import org.springframework.data.util.TypeContributor;
@ -67,7 +71,7 @@ import org.springframework.util.ClassUtils;
* @author Mark Paluch * @author Mark Paluch
* @since 3.0 * @since 3.0
*/ */
public class RepositoryRegistrationAotContribution implements BeanRegistrationAotContribution { public class RepositoryRegistrationAotContribution implements BeanRegistrationAotContribution, EnvironmentAware {
private static final Log logger = LogFactory.getLog(RepositoryRegistrationAotContribution.class); private static final Log logger = LogFactory.getLog(RepositoryRegistrationAotContribution.class);
@ -77,7 +81,8 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
private final AotRepositoryContext repositoryContext; private final AotRepositoryContext repositoryContext;
private @Nullable RepositoryContributor repositoryContributor; private @Nullable RepositoryContributor repositoryContributor;
private Lazy<Environment> environment = Lazy.of(StandardEnvironment::new);
private @Nullable BiFunction<AotRepositoryContext, GenerationContext, @Nullable RepositoryContributor> moduleContribution; private @Nullable BiFunction<AotRepositoryContext, GenerationContext, @Nullable RepositoryContributor> moduleContribution;
@ -213,6 +218,11 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
return this; return this;
} }
@Override
public void setEnvironment(Environment environment) {
this.environment = Lazy.of(environment);
}
@Override @Override
public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) { public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) {
@ -227,6 +237,8 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
this.repositoryContributor.contribute(generationContext); this.repositoryContributor.contribute(generationContext);
} }
} }
getRepositoryContext().typeConfigurations()
.forEach(typeConfiguration -> typeConfiguration.contribute(environment.get(), generationContext));
} }
@Override @Override
@ -261,19 +273,18 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
logTrace("Contributing repository information for [%s]", repositoryInformation.getRepositoryInterface()); logTrace("Contributing repository information for [%s]", repositoryInformation.getRepositoryInterface());
repositoryContext.typeConfiguration(repositoryInformation.getRepositoryInterface()) repositoryContext.typeConfiguration(repositoryInformation.getRepositoryInterface(),
.forReflectiveAccess(MemberCategory.INVOKE_PUBLIC_METHODS) // config -> config.forReflectiveAccess(MemberCategory.INVOKE_PUBLIC_METHODS).repositoryProxy());
.repositoryProxy();
repositoryContext.typeConfiguration(repositoryInformation.getRepositoryBaseClass()) repositoryContext.typeConfiguration(repositoryInformation.getRepositoryBaseClass(), config -> config
.forReflectiveAccess(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS); .forReflectiveAccess(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS));
repositoryContext.typeConfiguration(repositoryInformation.getDomainType()).forDataBinding().forQuerydsl(); repositoryContext.typeConfiguration(repositoryInformation.getDomainType(),
config -> config.forDataBinding().forQuerydsl());
// TODO: purposeful api for uses cases to have some internal logic // TODO: purposeful api for uses cases to have some internal logic
repositoryContext.getUserDomainTypes().stream() // repositoryContext.getUserDomainTypes() //
.map(repositoryContext::typeConfiguration) // .forEach(it -> repositoryContext.typeConfiguration(it, AotTypeConfiguration::contributeAccessors));
.forEach(AotTypeConfiguration::generateEntityInstantiator); //
// Repository Fragments // Repository Fragments
contributeFragments(contribution); contributeFragments(contribution);
@ -288,7 +299,7 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
.filter(Class::isInterface).forEach(type -> { .filter(Class::isInterface).forEach(type -> {
if (EntityProjectionIntrospector.ProjectionPredicate.typeHierarchy().test(type, if (EntityProjectionIntrospector.ProjectionPredicate.typeHierarchy().test(type,
repositoryInformation.getDomainType())) { repositoryInformation.getDomainType())) {
repositoryContext.typeConfiguration(type).usedAsProjectionInterface(); repositoryContext.typeConfiguration(type, AotTypeConfiguration::usedAsProjectionInterface);
} }
}); });
} }
@ -297,7 +308,7 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
for (RepositoryFragment<?> fragment : getRepositoryInformation().getFragments()) { for (RepositoryFragment<?> fragment : getRepositoryInformation().getFragments()) {
Class<?> repositoryFragmentType = fragment.getSignatureContributor(); Class<?> repositoryFragmentType = fragment.getSignatureContributor();
Optional<Class<?>> implementation = fragment.getImplementationClass(); Optional<Class<?>> implementation = fragment.getImplementationClass();
contribution.getRuntimeHints().reflection().registerType(repositoryFragmentType, hint -> { contribution.getRuntimeHints().reflection().registerType(repositoryFragmentType, hint -> {

4
src/main/java/org/springframework/data/repository/config/RepositoryRegistrationAotProcessor.java

@ -28,7 +28,6 @@ import org.jspecify.annotations.Nullable;
import org.springframework.aot.generate.GenerationContext; import org.springframework.aot.generate.GenerationContext;
import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.TypeReference;
import org.springframework.aot.hint.annotation.Reflective; import org.springframework.aot.hint.annotation.Reflective;
import org.springframework.aot.hint.annotation.ReflectiveRuntimeHintsRegistrar; import org.springframework.aot.hint.annotation.ReflectiveRuntimeHintsRegistrar;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
@ -42,6 +41,7 @@ import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.EnvironmentAware; import org.springframework.context.EnvironmentAware;
import org.springframework.core.annotation.MergedAnnotation; import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.data.aot.AotTypeConfiguration;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.core.env.EnvironmentCapable; import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.env.StandardEnvironment; import org.springframework.core.env.StandardEnvironment;
@ -126,7 +126,7 @@ public class RepositoryRegistrationAotProcessor
// arent we already registering the types in RepositoryRegistrationAotContribution#contributeRepositoryInfo? // arent we already registering the types in RepositoryRegistrationAotContribution#contributeRepositoryInfo?
registrar.registerRuntimeHints(hints, it); registrar.registerRuntimeHints(hints, it);
repositoryContext.instantiationCreator(TypeReference.of(it)).create(); repositoryContext.typeConfiguration(it, AotTypeConfiguration::contributeAccessors);
}); });
} }

214
src/test/java/org/springframework/data/aot/AotContextUnitTests.java

@ -15,96 +15,164 @@
*/ */
package org.springframework.data.aot; package org.springframework.data.aot;
import static org.mockito.Mockito.*;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.function.Consumer;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.CsvSource;
import org.mockito.Mock;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoSettings;
import org.springframework.aot.hint.TypeReference; import org.springframework.aot.hint.TypeReference;
import org.springframework.aot.test.generate.TestGenerationContext;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.data.aot.types.Address;
import org.springframework.data.aot.types.Customer;
import org.springframework.data.aot.types.EmptyType1;
import org.springframework.mock.env.MockEnvironment; import org.springframework.mock.env.MockEnvironment;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
* Tests for {@link AotContext}. * Unit tests for {@link AotContext}.
*
* *
* @author Mark Paluch
* @author Christoph Strobl * @author Christoph Strobl
*/ */
@MockitoSettings(strictness = org.mockito.quality.Strictness.LENIENT)
class AotContextUnitTests { class AotContextUnitTests {
@ParameterizedTest // GH-3322 @Mock BeanFactory beanFactory;
@CsvSource({ //
"'spring.aot.repositories.enabled', '', '', '', true", // @Mock AotMappingContext mappingContext;
"'spring.aot.repositories.enabled', 'true', '', '', true", //
"'spring.aot.repositories.enabled', 'false', '', '', false", // MockEnvironment mockEnvironment = new MockEnvironment();
"'spring.aot.repositories.enabled', '', 'commons', 'true', true", //
"'spring.aot.repositories.enabled', 'true', 'commons', 'true', true", // @Test // GH-2595
"'spring.aot.repositories.enabled', '', 'commons', 'false', false", // void shouldContributeAccessorByDefault() {
"'spring.aot.repositories.enabled', 'false', 'commons', 'true', false" //
}) contributeAccessor(Address.class);
void considersEnvironmentSettingsForGeneratedRepositories(String generalFlag, String generalValue, String storeName, verify(mappingContext).contribute(Address.class);
String storeValue, boolean enabled) { }
MockAotContext ctx = new MockAotContext(); @Test // GH-2595
if (StringUtils.hasText(generalFlag) && StringUtils.hasText(generalValue)) { void shouldConsiderDisabledAccessors() {
ctx.withProperty(generalFlag, generalValue);
} mockEnvironment.setProperty("spring.aot.data.accessors.enabled", "false");
if (StringUtils.hasText(storeName) && StringUtils.hasText(storeValue)) {
ctx.withProperty("spring.aot.%s.repositories.enabled".formatted(storeName), storeValue); contributeAccessor(Address.class);
}
verifyNoInteractions(mappingContext);
Assertions.assertThat(ctx.isGeneratedRepositoriesEnabled(storeName)).isEqualTo(enabled); }
}
@Test // GH-2595
static class MockAotContext implements AotContext { void shouldApplyExcludeFilters() {
private final MockEnvironment environment; mockEnvironment.setProperty("spring.aot.data.accessors.exclude",
Customer.class.getName() + " , " + EmptyType1.class.getName());
public MockAotContext() {
this.environment = new MockEnvironment(); contributeAccessor(Address.class, Customer.class, EmptyType1.class);
}
verify(mappingContext).contribute(Address.class);
MockAotContext withProperty(String key, String value) { verifyNoMoreInteractions(mappingContext);
environment.setProperty(key, value); }
return this;
} @Test // GH-2595
void shouldApplyIncludeExcludeFilters() {
@Override
public ConfigurableListableBeanFactory getBeanFactory() { mockEnvironment.setProperty("spring.aot.data.accessors.include", Customer.class.getPackageName() + ".Add*");
return Mockito.mock(ConfigurableListableBeanFactory.class); mockEnvironment.setProperty("spring.aot.data.accessors.exclude", Customer.class.getPackageName() + ".**");
}
contributeAccessor(Address.class, Customer.class, EmptyType1.class);
@Override
public TypeIntrospector introspectType(String typeName) { verify(mappingContext).contribute(Address.class);
return Mockito.mock(TypeIntrospector.class); verifyNoMoreInteractions(mappingContext);
} }
@Override private void contributeAccessor(Class<?>... classes) {
public IntrospectedBeanDefinition introspectBeanDefinition(String beanName) {
return Mockito.mock(IntrospectedBeanDefinition.class); DefaultAotContext context = new DefaultAotContext(beanFactory, mockEnvironment);
}
for (Class<?> aClass : classes) {
@Override context.typeConfiguration(aClass, AotTypeConfiguration::contributeAccessors);
public InstantiationCreator instantiationCreator(TypeReference typeReference) { }
return Mockito.mock(InstantiationCreator.class);
} context.typeConfigurations().forEach(it -> it.contribute(mockEnvironment, new TestGenerationContext()));
}
@Override
public AotTypeConfiguration typeConfiguration(TypeReference typeReference) { @ParameterizedTest // GH-3322
return null; @CsvSource({ //
} "'spring.aot.repositories.enabled', '', '', '', true", //
"'spring.aot.repositories.enabled', 'true', '', '', true", //
@Override "'spring.aot.repositories.enabled', 'false', '', '', false", //
public Collection<AotTypeConfiguration> typeConfigurations() { "'spring.aot.repositories.enabled', '', 'commons', 'true', true", //
return List.of(); "'spring.aot.repositories.enabled', 'true', 'commons', 'true', true", //
} "'spring.aot.repositories.enabled', '', 'commons', 'false', false", //
"'spring.aot.repositories.enabled', 'false', 'commons', 'true', false" //
@Override })
public Environment getEnvironment() { void considersEnvironmentSettingsForGeneratedRepositories(String generalFlag, String generalValue, String storeName,
return environment; String storeValue, boolean enabled) {
}
} MockAotContext ctx = new MockAotContext();
if (StringUtils.hasText(generalFlag) && StringUtils.hasText(generalValue)) {
ctx.withProperty(generalFlag, generalValue);
}
if (StringUtils.hasText(storeName) && StringUtils.hasText(storeValue)) {
ctx.withProperty("spring.aot.%s.repositories.enabled".formatted(storeName), storeValue);
}
Assertions.assertThat(ctx.isGeneratedRepositoriesEnabled(storeName)).isEqualTo(enabled);
}
static class MockAotContext implements AotContext {
private final MockEnvironment environment;
public MockAotContext() {
this.environment = new MockEnvironment();
}
MockAotContext withProperty(String key, String value) {
environment.setProperty(key, value);
return this;
}
@Override
public ConfigurableListableBeanFactory getBeanFactory() {
return Mockito.mock(ConfigurableListableBeanFactory.class);
}
@Override
public TypeIntrospector introspectType(String typeName) {
return Mockito.mock(TypeIntrospector.class);
}
@Override
public IntrospectedBeanDefinition introspectBeanDefinition(String beanName) {
return Mockito.mock(IntrospectedBeanDefinition.class);
}
@Override
public void typeConfiguration(Class<?> type, Consumer<AotTypeConfiguration> configurationConsumer) {
}
@Override
public Collection<AotTypeConfiguration> typeConfigurations() {
return List.of();
}
@Override
public Environment getEnvironment() {
return environment;
}
}
} }

10
src/test/java/org/springframework/data/repository/aot/generate/DummyModuleAotRepositoryContext.java

@ -20,10 +20,9 @@ import java.lang.annotation.Annotation;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.TypeReference;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.annotation.MergedAnnotation; import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
@ -80,13 +79,8 @@ class DummyModuleAotRepositoryContext implements AotRepositoryContext {
} }
@Override @Override
public InstantiationCreator instantiationCreator(TypeReference typeReference) { public void typeConfiguration(Class<?> type, Consumer<AotTypeConfiguration> configurationConsumer) {
return null;
}
@Override
public AotTypeConfiguration typeConfiguration(TypeReference typeReference) {
return null;
} }
@Override @Override

Loading…
Cancel
Save