@ -19,7 +19,6 @@ import java.io.Serializable;
import java.lang.annotation.Annotation ;
import java.lang.annotation.Annotation ;
import java.util.ArrayList ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.Arrays ;
import java.util.Collection ;
import java.util.Collections ;
import java.util.Collections ;
import java.util.List ;
import java.util.List ;
import java.util.Map ;
import java.util.Map ;
@ -27,7 +26,6 @@ import java.util.Optional;
import java.util.Set ;
import java.util.Set ;
import java.util.function.BiConsumer ;
import java.util.function.BiConsumer ;
import java.util.function.Predicate ;
import java.util.function.Predicate ;
import java.util.stream.Collectors ;
import org.springframework.aop.SpringProxy ;
import org.springframework.aop.SpringProxy ;
import org.springframework.aop.framework.Advised ;
import org.springframework.aop.framework.Advised ;
@ -47,12 +45,11 @@ import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.data.projection.EntityProjectionIntrospector ;
import org.springframework.data.projection.EntityProjectionIntrospector ;
import org.springframework.data.projection.TargetAware ;
import org.springframework.data.projection.TargetAware ;
import org.springframework.data.repository.Repository ;
import org.springframework.data.repository.Repository ;
import org.springframework.data.repository.config.RepositoryConfiguration ;
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport ;
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport ;
import org.springframework.data.repository.config.RepositoryMetadata ;
import org.springframework.data.repository.core.RepositoryInformation ;
import org.springframework.data.repository.core.RepositoryInformation ;
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport ;
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport ;
import org.springframework.data.repository.core.support.RepositoryFragment ;
import org.springframework.data.repository.core.support.RepositoryFragment ;
import org.springframework.lang.NonNull ;
import org.springframework.lang.Nullable ;
import org.springframework.lang.Nullable ;
import org.springframework.stereotype.Component ;
import org.springframework.stereotype.Component ;
import org.springframework.util.Assert ;
import org.springframework.util.Assert ;
@ -62,29 +59,24 @@ import org.springframework.util.ClassUtils;
* { @link BeanRegistrationAotContribution } used to contribute repository registrations .
* { @link BeanRegistrationAotContribution } used to contribute repository registrations .
*
*
* @author John Blum
* @author John Blum
* @see org . springframework . aot . generate . GenerationContext
* @since 3 . 0
* @see org . springframework . beans . factory . aot . BeanRegistrationAotContribution
* @see org . springframework . beans . factory . support . RegisteredBean
* @see org . springframework . data . aot . RepositoryRegistrationAotProcessor
* @since 3 . 0 . 0
* /
* /
public class RepositoryRegistrationAotContribution implements BeanRegistrationAotContribution {
public class RepositoryRegistrationAotContribution implements BeanRegistrationAotContribution {
private static final String KOTLIN_COROUTINE_REPOSITORY_TYPE_NAME =
private static final String KOTLIN_COROUTINE_REPOSITORY_TYPE_NAME = "org.springframework.data.repository.kotlin.CoroutineCrudRepository" ;
"org.springframework.data.repository.kotlin.CoroutineCrudRepository" ;
/ * *
/ * *
* Factory method used to construct a new instance of { @link RepositoryRegistrationAotContribution } initialized with
* Factory method used to construct a new instance of { @link RepositoryRegistrationAotContribution } initialized with
* the given , required { @link RepositoryRegistrationAotProcessor } from which this contribution was created .
* the given , required { @link RepositoryRegistrationAotProcessor } from which this contribution was created .
*
*
* @param repositoryRegistrationAotProcessor reference back to the { @link RepositoryRegistrationAotProcessor } from which this
* @param repositoryRegistrationAotProcessor reference back to the { @link RepositoryRegistrationAotProcessor } from
* contribution was created .
* which this contribution was created .
* @return a new instance of { @link RepositoryRegistrationAotContribution } .
* @return a new instance of { @link RepositoryRegistrationAotContribution } .
* @throws IllegalArgumentException if the { @link RepositoryRegistrationAotProcessor } is { @literal null } .
* @throws IllegalArgumentException if the { @link RepositoryRegistrationAotProcessor } is { @literal null } .
* @see org . springframework . data . aot . RepositoryRegistrationAotProcessor
* @see org . springframework . data . aot . RepositoryRegistrationAotProcessor
* /
* /
public static RepositoryRegistrationAotContribution fromProcessor (
public static RepositoryRegistrationAotContribution fromProcessor (
@NonNull RepositoryRegistrationAotProcessor repositoryRegistrationAotProcessor ) {
RepositoryRegistrationAotProcessor repositoryRegistrationAotProcessor ) {
return new RepositoryRegistrationAotContribution ( repositoryRegistrationAotProcessor ) ;
return new RepositoryRegistrationAotContribution ( repositoryRegistrationAotProcessor ) ;
}
}
@ -93,28 +85,25 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
private BiConsumer < AotRepositoryContext , GenerationContext > moduleContribution ;
private BiConsumer < AotRepositoryContext , GenerationContext > moduleContribution ;
@NonNull
private final RepositoryRegistrationAotProcessor repositoryRegistrationAotProcessor ;
private final RepositoryRegistrationAotProcessor repositoryRegistrationAotProcessor ;
/ * *
/ * *
* Constructs a new instance of the { @link RepositoryRegistrationAotContribution } initialized with the given ,
* Constructs a new instance of the { @link RepositoryRegistrationAotContribution } initialized with the given , required
* required { @link RepositoryRegistrationAotProcessor } from which this contribution was created .
* { @link RepositoryRegistrationAotProcessor } from which this contribution was created .
*
*
* @param repositoryRegistrationAotProcessor reference back to the { @link RepositoryRegistrationAotProcessor } from which this
* @param repositoryRegistrationAotProcessor reference back to the { @link RepositoryRegistrationAotProcessor } from
* contribution was created .
* which this contribution was created .
* @throws IllegalArgumentException if the { @link RepositoryRegistrationAotProcessor } is { @literal null } .
* @throws IllegalArgumentException if the { @link RepositoryRegistrationAotProcessor } is { @literal null } .
* @see org . springframework . data . aot . RepositoryRegistrationAotProcessor
* @see org . springframework . data . aot . RepositoryRegistrationAotProcessor
* /
* /
protected RepositoryRegistrationAotContribution (
protected RepositoryRegistrationAotContribution (
@NonNull RepositoryRegistrationAotProcessor repositoryRegistrationAotProcessor ) {
RepositoryRegistrationAotProcessor repositoryRegistrationAotProcessor ) {
Assert . notNull ( repositoryRegistrationAotProcessor ,
Assert . notNull ( repositoryRegistrationAotProcessor , "RepositoryRegistrationAotProcessor must not be null" ) ;
"RepositoryRegistrationAotProcessor must not be null" ) ;
this . repositoryRegistrationAotProcessor = repositoryRegistrationAotProcessor ;
this . repositoryRegistrationAotProcessor = repositoryRegistrationAotProcessor ;
}
}
@NonNull
protected ConfigurableListableBeanFactory getBeanFactory ( ) {
protected ConfigurableListableBeanFactory getBeanFactory ( ) {
return getRepositoryRegistrationAotProcessor ( ) . getBeanFactory ( ) ;
return getRepositoryRegistrationAotProcessor ( ) . getBeanFactory ( ) ;
}
}
@ -123,7 +112,6 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
return Optional . ofNullable ( this . moduleContribution ) ;
return Optional . ofNullable ( this . moduleContribution ) ;
}
}
@NonNull
protected AotRepositoryContext getRepositoryContext ( ) {
protected AotRepositoryContext getRepositoryContext ( ) {
Assert . state ( this . repositoryContext ! = null ,
Assert . state ( this . repositoryContext ! = null ,
@ -132,7 +120,6 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
return this . repositoryContext ;
return this . repositoryContext ;
}
}
@NonNull
protected RepositoryRegistrationAotProcessor getRepositoryRegistrationAotProcessor ( ) {
protected RepositoryRegistrationAotProcessor getRepositoryRegistrationAotProcessor ( ) {
return this . repositoryRegistrationAotProcessor ;
return this . repositoryRegistrationAotProcessor ;
}
}
@ -146,20 +133,21 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
}
}
/ * *
/ * *
* Builds a { @link RepositoryRegistrationAotContribution } for given , required { @link RegisteredBean }
* Builds a { @link RepositoryRegistrationAotContribution } for given , required { @link RegisteredBean } representing the
* representing the { @link Repository } registered in the bean registry .
* { @link Repository } registered in the bean registry .
*
*
* @param repositoryBean { @link RegisteredBean } for the { @link Repository } ; must not be { @literal null } .
* @param repositoryBean { @link RegisteredBean } for the { @link Repository } ; must not be { @literal null } .
* @return a { @link RepositoryRegistrationAotContribution } to contribute AOT metadata and code
* @return a { @link RepositoryRegistrationAotContribution } to contribute AOT metadata and code for the
* for the { @link Repository } { @link RegisteredBean } .
* { @link Repository } { @link RegisteredBean } .
* @throws IllegalArgumentException if the { @link RegisteredBean } is { @literal null } .
* @throws IllegalArgumentException if the { @link RegisteredBean } is { @literal null } .
* @see org . springframework . beans . factory . support . RegisteredBean
* @see org . springframework . beans . factory . support . RegisteredBean
* /
* /
public RepositoryRegistrationAotContribution forBean ( @NonNull RegisteredBean repositoryBean ) {
public RepositoryRegistrationAotContribution forBean ( RegisteredBean repositoryBean ) {
Assert . notNull ( repositoryBean , "The RegisteredBean for the repository must not be null" ) ;
Assert . notNull ( repositoryBean , "The RegisteredBean for the repository must not be null" ) ;
RepositoryMetadata < ? > repositoryMetadata = getRepositoryRegistrationAotProcessor ( ) . getRepositoryMetadata ( repositoryBean ) ;
RepositoryConfiguration < ? > repositoryMetadata = getRepositoryRegistrationAotProcessor ( )
. getRepositoryMetadata ( repositoryBean ) ;
this . repositoryContext = buildAotRepositoryContext ( repositoryBean , repositoryMetadata ) ;
this . repositoryContext = buildAotRepositoryContext ( repositoryBean , repositoryMetadata ) ;
@ -168,14 +156,14 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
return this ;
return this ;
}
}
protected DefaultAotRepositoryContext buildAotRepositoryContext ( @NonNull RegisteredBean bean ,
protected DefaultAotRepositoryContext buildAotRepositoryContext ( RegisteredBean bean ,
@NonNull RepositoryMetadata < ? > repositoryMetadata ) {
RepositoryConfiguration < ? > repositoryMetadata ) {
RepositoryInformation repositoryInformation = resolveRepositoryInformation ( repositoryMetadata ) ;
RepositoryInformation repositoryInformation = resolveRepositoryInformation ( repositoryMetadata ) ;
DefaultAotRepositoryContext repositoryContext = new DefaultAotRepositoryContext ( ) ;
DefaultAotRepositoryContext repositoryContext = new DefaultAotRepositoryContext (
AotContext . from ( this . getBeanFactory ( ) ) ) ;
repositoryContext . setAotContext ( this : : getBeanFactory ) ;
repositoryContext . setBeanName ( bean . getBeanName ( ) ) ;
repositoryContext . setBeanName ( bean . getBeanName ( ) ) ;
repositoryContext . setBasePackages ( repositoryMetadata . getBasePackages ( ) . toSet ( ) ) ;
repositoryContext . setBasePackages ( repositoryMetadata . getBasePackages ( ) . toSet ( ) ) ;
repositoryContext . setIdentifyingAnnotations ( resolveIdentifyingAnnotations ( ) ) ;
repositoryContext . setIdentifyingAnnotations ( resolveIdentifyingAnnotations ( ) ) ;
@ -194,13 +182,13 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
// all stores will be included in the resulting Set.
// all stores will be included in the resulting Set.
// When using AOT, is multi-store mode allowed? I don't see why not, but does this work correctly
// When using AOT, is multi-store mode allowed? I don't see why not, but does this work correctly
// with AOT, ATM?
// with AOT, ATM?
Map < String , RepositoryConfigurationExtensionSupport > repositoryConfigurationExtensionBeans =
Map < String , RepositoryConfigurationExtensionSupport > repositoryConfigurationExtensionBeans = getBeanFactory ( )
getBeanFactory ( ) . getBeansOfType ( RepositoryConfigurationExtensionSupport . class ) ;
. getBeansOfType ( RepositoryConfigurationExtensionSupport . class ) ;
// repositoryConfigurationExtensionBeans.values().stream()
// repositoryConfigurationExtensionBeans.values().stream()
// .map(RepositoryConfigurationExtensionSupport::getIdentifyingAnnotations)
// .map(RepositoryConfigurationExtensionSupport::getIdentifyingAnnotations)
// .flatMap(Collection::stream)
// .flatMap(Collection::stream)
// .collect(Collectors.toCollection(() -> identifyingAnnotations));
// .collect(Collectors.toCollection(() -> identifyingAnnotations));
} catch ( Throwable ignore ) {
} catch ( Throwable ignore ) {
// Possible BeansException because no bean exists of type RepositoryConfigurationExtension,
// Possible BeansException because no bean exists of type RepositoryConfigurationExtension,
@ -210,25 +198,24 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
return identifyingAnnotations ;
return identifyingAnnotations ;
}
}
private RepositoryInformation resolveRepositoryInformation ( RepositoryMetadata < ? > repositoryMetadata ) {
private RepositoryInformation resolveRepositoryInformation ( RepositoryConfiguration < ? > repositoryMetadata ) {
return RepositoryBeanDefinitionReader . readRepositoryInformation ( repositoryMetadata , getBeanFactory ( ) ) ;
return RepositoryBeanDefinitionReader . readRepositoryInformation ( repositoryMetadata , getBeanFactory ( ) ) ;
}
}
/ * *
/ * *
* Helps the AOT processing render the { @link FactoryBean } type correctly that is used to tell the outcome of the { @link FactoryBean } .
* Helps the AOT processing render the { @link FactoryBean } type correctly that is used to tell the outcome of the
*
* { @link FactoryBean } . We just need to set the target { @link Repository } { @link Class type } of the
* We just need to set the target { @link Repository } { @link Class type } of the { @link RepositoryFactoryBeanSupport }
* { @link RepositoryFactoryBeanSupport } while keeping the actual ID and DomainType set to { @link Object } . If the
* while keeping the actual ID and DomainType set to { @link Object } . If the generic type signature does not match ,
* generic type signature does not match , then we do not try to resolve and remap the types , but rather set the
* then we do not try to resolve and remap the types , but rather set the { @literal factoryBeanObjectType } attribute
* { @literal factoryBeanObjectType } attribute on the { @link RootBeanDefinition } .
* on the { @link RootBeanDefinition } .
* /
* /
protected void enhanceRepositoryBeanDefinition ( @NonNull RegisteredBean repositoryBean ,
protected void enhanceRepositoryBeanDefinition ( RegisteredBean repositoryBean ,
@NonNull RepositoryMetadata < ? > repositoryMetadata , @NonNull AotRepositoryContext repositoryContext ) {
RepositoryConfiguration < ? > repositoryMetadata , AotRepositoryContext repositoryContext ) {
logTrace ( String . format ( "Enhancing repository factory bean definition [%s]" , repositoryBean . getBeanName ( ) ) ) ;
logTrace ( String . format ( "Enhancing repository factory bean definition [%s]" , repositoryBean . getBeanName ( ) ) ) ;
Class < ? > repositoryFactoryBeanType = repositoryContext
Class < ? > repositoryFactoryBeanType = repositoryContext
. resolve Type( repositoryMetadata . getRepositoryFactoryBeanClassName ( ) )
. introspect Type ( repositoryMetadata . getRepositoryFactoryBeanClassName ( ) ) . resolveType ( )
. orElse ( RepositoryFactoryBeanSupport . class ) ;
. orElse ( RepositoryFactoryBeanSupport . class ) ;
ResolvableType resolvedRepositoryFactoryBeanType = ResolvableType . forClass ( repositoryFactoryBeanType ) ;
ResolvableType resolvedRepositoryFactoryBeanType = ResolvableType . forClass ( repositoryFactoryBeanType ) ;
@ -246,7 +233,7 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
}
}
private boolean isRepositoryWithTypeParameters ( ResolvableType type ) {
private boolean isRepositoryWithTypeParameters ( ResolvableType type ) {
return type ! = null & & type . getGenerics ( ) . length = = 3 ;
return type . getGenerics ( ) . length = = 3 ;
}
}
/ * *
/ * *
@ -255,7 +242,7 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
* @param moduleContribution { @link BiConsumer } used by data modules to submit contributions ; can be { @literal null } .
* @param moduleContribution { @link BiConsumer } used by data modules to submit contributions ; can be { @literal null } .
* @return this .
* @return this .
* /
* /
@NonNull
@SuppressWarnings ( "unused" )
@SuppressWarnings ( "unused" )
public RepositoryRegistrationAotContribution withModuleContribution (
public RepositoryRegistrationAotContribution withModuleContribution (
@Nullable BiConsumer < AotRepositoryContext , GenerationContext > moduleContribution ) {
@Nullable BiConsumer < AotRepositoryContext , GenerationContext > moduleContribution ) {
@ -264,29 +251,27 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
}
}
@Override
@Override
public void applyTo ( @NonNull GenerationContext generationContext ,
public void applyTo ( GenerationContext generationContext , BeanRegistrationCode beanRegistrationCode ) {
@NonNull BeanRegistrationCode beanRegistrationCode ) {
contributeRepositoryInfo ( this . repositoryContext , generationContext ) ;
contributeRepositoryInfo ( this . repositoryContext , generationContext ) ;
getModuleContribution ( ) . ifPresent ( it - > it . accept ( getRepositoryContext ( ) , generationContext ) ) ;
getModuleContribution ( ) . ifPresent ( it - > it . accept ( getRepositoryContext ( ) , generationContext ) ) ;
}
}
private void contributeRepositoryInfo ( @NonNull AotRepositoryContext repositoryContext ,
private void contributeRepositoryInfo ( AotRepositoryContext repositoryContext , GenerationContext contribution ) {
@NonNull GenerationContext contribution ) {
RepositoryInformation repositoryInformation = getRepositoryInformation ( ) ;
RepositoryInformation repositoryInformation = getRepositoryInformation ( ) ;
logTrace ( "Contributing repository information for [%s]" ,
logTrace ( "Contributing repository information for [%s]" , repositoryInformation . getRepositoryInterface ( ) ) ;
repositoryInformation . getRepositoryInterface ( ) ) ;
// TODO: is this the way?
// TODO: is this the way?
contribution . getRuntimeHints ( ) . reflection ( )
contribution . getRuntimeHints ( ) . reflection ( )
. registerType ( repositoryInformation . getRepositoryInterface ( ) , hint - >
. registerType ( repositoryInformation . getRepositoryInterface ( ) ,
hint . withMembers ( MemberCategory . INVOKE_PUBLIC_METHODS ) )
hint - > hint . withMembers ( MemberCategory . INVOKE_PUBLIC_METHODS ) )
. registerType ( repositoryInformation . getRepositoryBaseClass ( ) , hint - >
. registerType ( repositoryInformation . getRepositoryBaseClass ( ) ,
hint . withMembers ( MemberCategory . INVOKE_DECLARED_CONSTRUCTORS , MemberCategory . INVOKE_PUBLIC_METHODS ) )
hint - > hint . withMembers ( MemberCategory . INVOKE_DECLARED_CONSTRUCTORS , MemberCategory . INVOKE_PUBLIC_METHODS ) )
. registerType ( repositoryInformation . getDomainType ( ) , hint - >
. registerType ( repositoryInformation . getDomainType ( ) ,
hint . withMembers ( MemberCategory . INVOKE_DECLARED_CONSTRUCTORS , MemberCategory . INVOKE_DECLARED_METHODS , MemberCategory . DECLARED_FIELDS ) ) ;
hint - > hint . withMembers ( MemberCategory . INVOKE_DECLARED_CONSTRUCTORS ,
MemberCategory . INVOKE_DECLARED_METHODS , MemberCategory . DECLARED_FIELDS ) ) ;
// Repository Fragments
// Repository Fragments
for ( RepositoryFragment < ? > fragment : getRepositoryInformation ( ) . getFragments ( ) ) {
for ( RepositoryFragment < ? > fragment : getRepositoryInformation ( ) . getFragments ( ) ) {
@ -308,7 +293,7 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
SpringProxy . class , Advised . class , DecoratingProxy . class ) ;
SpringProxy . class , Advised . class , DecoratingProxy . class ) ;
// Transactional Repository Proxy
// Transactional Repository Proxy
//repositoryContext.ifTransactionManagerPresent(transactionManagerBeanNames -> {
// repositoryContext.ifTransactionManagerPresent(transactionManagerBeanNames -> {
// TODO: Is the following double JDK Proxy registration above necessary or would a single JDK Proxy
// TODO: Is the following double JDK Proxy registration above necessary or would a single JDK Proxy
// registration suffice?
// registration suffice?
@ -316,8 +301,8 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
// the additional Serializable TypeReference?
// the additional Serializable TypeReference?
// NOTE: Using a single JDK Proxy registration causes the
// NOTE: Using a single JDK Proxy registration causes the
// simpleRepositoryWithTxManagerNoKotlinNoReactiveButComponent() test case method to fail.
// simpleRepositoryWithTxManagerNoKotlinNoReactiveButComponent() test case method to fail.
List < TypeReference > transactionalRepositoryProxyTypeReferences =
List < TypeReference > transactionalRepositoryProxyTypeReferences = transactionalRepositoryProxyTypeReferences (
transactionalRepositoryProxyTypeReferences ( repositoryInformation ) ;
repositoryInformation ) ;
contribution . getRuntimeHints ( ) . proxies ( )
contribution . getRuntimeHints ( ) . proxies ( )
. registerJdkProxy ( transactionalRepositoryProxyTypeReferences . toArray ( new TypeReference [ 0 ] ) ) ;
. registerJdkProxy ( transactionalRepositoryProxyTypeReferences . toArray ( new TypeReference [ 0 ] ) ) ;
@ -327,7 +312,7 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
contribution . getRuntimeHints ( ) . proxies ( )
contribution . getRuntimeHints ( ) . proxies ( )
. registerJdkProxy ( transactionalRepositoryProxyTypeReferences . toArray ( new TypeReference [ 0 ] ) ) ;
. registerJdkProxy ( transactionalRepositoryProxyTypeReferences . toArray ( new TypeReference [ 0 ] ) ) ;
}
}
//});
// });
// Reactive Repositories
// Reactive Repositories
if ( repositoryInformation . isReactiveRepository ( ) ) {
if ( repositoryInformation . isReactiveRepository ( ) ) {
@ -342,12 +327,10 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
}
}
// Repository query methods
// Repository query methods
repositoryInformation . getQueryMethods ( )
repositoryInformation . getQueryMethods ( ) . map ( repositoryInformation : : getReturnedDomainClass )
. map ( repositoryInformation : : getReturnedDomainClass )
. filter ( Class : : isInterface ) . forEach ( type - > {
. filter ( Class : : isInterface )
if ( EntityProjectionIntrospector . ProjectionPredicate . typeHierarchy ( ) . test ( type ,
. forEach ( type - > {
repositoryInformation . getDomainType ( ) ) ) {
if ( EntityProjectionIntrospector . ProjectionPredicate . typeHierarchy ( )
. test ( type , repositoryInformation . getDomainType ( ) ) ) {
contributeProjection ( type , contribution ) ;
contributeProjection ( type , contribution ) ;
}
}
} ) ;
} ) ;
@ -360,58 +343,52 @@ public class RepositoryRegistrationAotContribution implements BeanRegistrationAo
private boolean isKotlinCoroutineRepository ( AotRepositoryContext repositoryContext ,
private boolean isKotlinCoroutineRepository ( AotRepositoryContext repositoryContext ,
RepositoryInformation repositoryInformation ) {
RepositoryInformation repositoryInformation ) {
return repositoryContext . resolveType ( KOTLIN_COROUTINE_REPOSITORY_TYPE_NAME )
return repositoryContext . introspectType ( KOTLIN_COROUTINE_REPOSITORY_TYPE_NAME ) . resolveType ( )
. filter ( it - > ClassUtils . isAssignable ( it , repositoryInformation . getRepositoryInterface ( ) ) )
. filter ( it - > ClassUtils . isAssignable ( it , repositoryInformation . getRepositoryInterface ( ) ) ) . isPresent ( ) ;
. isPresent ( ) ;
}
}
private List < TypeReference > kotlinRepositoryReflectionTypeReferences ( ) {
private List < TypeReference > kotlinRepositoryReflectionTypeReferences ( ) {
return new ArrayList < > ( Arrays . asList (
return new ArrayList < > (
TypeReference . of ( "org.springframework.data.repository.kotlin.CoroutineCrudRepository" ) ,
Arrays . asList ( TypeReference . of ( "org.springframework.data.repository.kotlin.CoroutineCrudRepository" ) ,
TypeReference . of ( Repository . class ) ,
TypeReference . of ( Repository . class ) , //
TypeReference . of ( Iterable . class ) ,
TypeReference . of ( Iterable . class ) , //
TypeReference . of ( "kotlinx.coroutines.flow.Flow" ) ,
TypeReference . of ( "kotlinx.coroutines.flow.Flow" ) , //
TypeReference . of ( "kotlin.collections.Iterable" ) ,
TypeReference . of ( "kotlin.collections.Iterable" ) , //
TypeReference . of ( "kotlin.Unit" ) ,
TypeReference . of ( "kotlin.Unit" ) , //
TypeReference . of ( "kotlin.Long" ) ,
TypeReference . of ( "kotlin.Long" ) , //
TypeReference . of ( "kotlin.Boolean" )
TypeReference . of ( "kotlin.Boolean" ) ) ) ;
) ) ;
}
}
private List < TypeReference > transactionalRepositoryProxyTypeReferences ( RepositoryInformation repositoryInformation ) {
private List < TypeReference > transactionalRepositoryProxyTypeReferences ( RepositoryInformation repositoryInformation ) {
return new ArrayList < > ( Arrays . asList (
return new ArrayList < > ( Arrays . asList ( TypeReference . of ( repositoryInformation . getRepositoryInterface ( ) ) ,
TypeReference . of ( repositoryInformation . getRepositoryInterface ( ) ) ,
TypeReference . of ( Repository . class ) , //
TypeReference . of ( Repository . class ) ,
TypeReference . of ( "org.springframework.transaction.interceptor.TransactionalProxy" ) , //
TypeReference . of ( "org.springframework.transaction.interceptor.TransactionalProxy" ) ,
TypeReference . of ( "org.springframework.aop.framework.Advised" ) , //
TypeReference . of ( "org.springframework.aop.framework.Advised" ) ,
TypeReference . of ( DecoratingProxy . class ) ) ) ;
TypeReference . of ( DecoratingProxy . class )
) ) ;
}
}
private void contributeProjection ( Class < ? > type , GenerationContext generationContext ) {
private void contributeProjection ( Class < ? > type , GenerationContext generationContext ) {
generationContext . getRuntimeHints ( ) . proxies ( )
generationContext . getRuntimeHints ( ) . proxies ( ) . registerJdkProxy ( type , TargetAware . class , SpringProxy . class ,
. registerJdkProxy ( type , TargetAware . class , SpringProxy . class , DecoratingProxy . class ) ;
DecoratingProxy . class ) ;
}
}
static boolean isJavaOrPrimitiveType ( Class < ? > type ) {
static boolean isJavaOrPrimitiveType ( Class < ? > type ) {
return TypeUtils . type ( type ) . isPartOf ( "java" ) //
return TypeUtils . type ( type ) . isPartOf ( "java" )
| | ClassUtils . isPrimitiveOrWrapper ( type ) //
| | type . isPrimitive ( )
| | ClassUtils . isPrimitiveArray ( type ) ; //
| | ClassUtils . isPrimitiveArray ( type ) ;
}
}
static boolean isSpringDataManagedAnnotation ( MergedAnnotation < ? > annotation ) {
static boolean isSpringDataManagedAnnotation ( @Nullable MergedAnnotation < ? > annotation ) {
return annotation ! = null
return annotation ! = null & & ( isInSpringDataNamespace ( annotation . getType ( ) )
& & ( isInSpringDataNamespace ( annotation . getType ( ) ) | | annotation . getMetaTypes ( ) . stream ( )
| | annotation . getMetaTypes ( ) . stream ( ) . anyMatch ( RepositoryRegistrationAotContribution : : isInSpringDataNamespace ) ) ;
. anyMatch ( RepositoryRegistrationAotContribution : : isInSpringDataNamespace ) ) ;
}
}
static boolean isInSpringDataNamespace ( Class < ? > type ) {
static boolean isInSpringDataNamespace ( Class < ? > type ) {
return type ! = null & & type . getPackage ( ) . getName ( ) . startsWith ( TypeContributor . DATA_NAMESPACE ) ;
return type . getPackage ( ) . getName ( ) . startsWith ( TypeContributor . DATA_NAMESPACE ) ;
}
}
static void contributeType ( Class < ? > type , GenerationContext generationContext ) {
static void contributeType ( Class < ? > type , GenerationContext generationContext ) {