@@ -110,7 +110,7 @@ public abstract class RepositoryFactorySupport
110110 CONVERSION_SERVICE .removeConvertible (Object .class , Object .class );
111111 }
112112
113- private final Map <RepositoryInformationCacheKey , RepositoryInformation > repositoryInformationCache ;
113+ private final Map <RepositoryInformationCacheKey , RepositorySub > repositoryInformationCache ;
114114 private final List <RepositoryProxyPostProcessor > postProcessors ;
115115
116116 private @ Nullable Class <?> repositoryBaseClass ;
@@ -130,7 +130,7 @@ public abstract class RepositoryFactorySupport
130130 @ SuppressWarnings ("null" )
131131 public RepositoryFactorySupport () {
132132
133- this .repositoryInformationCache = new HashMap <>(16 );
133+ this .repositoryInformationCache = new HashMap <>(8 );
134134 this .postProcessors = new ArrayList <>();
135135
136136 this .namedQueries = PropertiesBasedNamedQueries .EMPTY ;
@@ -294,16 +294,6 @@ protected RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata
294294 return RepositoryFragments .empty ();
295295 }
296296
297- /**
298- * Creates {@link RepositoryComposition} based on {@link RepositoryMetadata} for repository-specific method handling.
299- *
300- * @param metadata the repository metadata to use.
301- * @return repository composition.
302- */
303- private RepositoryComposition getRepositoryComposition (RepositoryMetadata metadata ) {
304- return RepositoryComposition .fromMetadata (metadata );
305- }
306-
307297 /**
308298 * Returns a repository instance for the given interface.
309299 *
@@ -362,8 +352,9 @@ public <T> T getRepository(Class<T> repositoryInterface, RepositoryFragments fra
362352 repositoryInterface );
363353 repositoryCompositionStep .tag ("fragment.count" , String .valueOf (fragments .size ()));
364354
365- RepositoryComposition composition = getRepositoryComposition (metadata , fragments );
366- RepositoryInformation information = getRepositoryInformation (metadata , composition );
355+ RepositorySub stub = getRepositoryStub (metadata , fragments );
356+ RepositoryComposition composition = stub .composition ();
357+ RepositoryInformation information = stub .information ();
367358
368359 repositoryCompositionStep .tag ("fragments" , () -> {
369360
@@ -493,47 +484,35 @@ protected RepositoryMetadata getRepositoryMetadata(Class<?> repositoryInterface)
493484 * @return will never be {@literal null}.
494485 */
495486 protected RepositoryInformation getRepositoryInformation (RepositoryMetadata metadata , RepositoryFragments fragments ) {
496- return getRepositoryInformation (metadata , getRepositoryComposition ( metadata , fragments ));
487+ return getRepositoryStub (metadata , fragments ). information ( );
497488 }
498489
499490 /**
500- * Returns the {@link RepositoryComposition} for the given {@link RepositoryMetadata} and extra
501- * {@link RepositoryFragments}.
502- *
503- * @param metadata must not be {@literal null}.
504- * @param fragments must not be {@literal null}.
505- * @return will never be {@literal null}.
506- */
507- private RepositoryComposition getRepositoryComposition (RepositoryMetadata metadata , RepositoryFragments fragments ) {
508-
509- Assert .notNull (metadata , "RepositoryMetadata must not be null" );
510- Assert .notNull (fragments , "RepositoryFragments must not be null" );
511-
512- RepositoryComposition composition = getRepositoryComposition (metadata );
513- RepositoryFragments repositoryAspects = getRepositoryFragments (metadata );
514-
515- return composition .append (fragments ).append (repositoryAspects );
516- }
517-
518- /**
519- * Returns the {@link RepositoryInformation} for the given repository interface.
491+ * Returns the cached {@link RepositorySub} for the given repository and composition. {@link RepositoryMetadata} is a
492+ * strong cache key while {@link RepositoryFragments} contributes a light-weight caching component by using only the
493+ * fragments hash code. In a typical Spring scenario, that shouldn't impose issues as one repository factory produces
494+ * only a single repository instance for one repository interface. Things might be different when using various
495+ * fragments for the same repository interface.
520496 *
521497 * @param metadata
522- * @param composition
498+ * @param fragments
523499 * @return
524500 */
525- private RepositoryInformation getRepositoryInformation (RepositoryMetadata metadata ,
526- RepositoryComposition composition ) {
501+ private RepositorySub getRepositoryStub (RepositoryMetadata metadata , RepositoryFragments fragments ) {
527502
528- RepositoryInformationCacheKey cacheKey = new RepositoryInformationCacheKey (metadata , composition );
503+ RepositoryInformationCacheKey cacheKey = new RepositoryInformationCacheKey (metadata , fragments );
529504
530505 synchronized (repositoryInformationCache ) {
531506
532507 return repositoryInformationCache .computeIfAbsent (cacheKey , key -> {
533508
509+ RepositoryComposition composition = RepositoryComposition .fromMetadata (metadata );
510+ RepositoryFragments repositoryAspects = getRepositoryFragments (metadata );
511+ composition = composition .append (fragments ).append (repositoryAspects );
512+
534513 Class <?> baseClass = repositoryBaseClass != null ? repositoryBaseClass : getRepositoryBaseClass (metadata );
535514
536- return new DefaultRepositoryInformation (metadata , baseClass , composition );
515+ return new RepositorySub ( new DefaultRepositoryInformation (metadata , baseClass , composition ) , composition );
537516 });
538517 }
539518 }
@@ -816,6 +795,18 @@ public List<QueryMethod> getQueryMethods() {
816795 }
817796 }
818797
798+ /**
799+ * Repository stub holding {@link RepositoryInformation} and {@link RepositoryComposition}.
800+ *
801+ * @param information
802+ * @param composition
803+ * @author Mark Paluch
804+ * @since 3.4.4
805+ */
806+ record RepositorySub (RepositoryInformation information , RepositoryComposition composition ) {
807+
808+ }
809+
819810 /**
820811 * Simple value object to build up keys to cache {@link RepositoryInformation} instances.
821812 *
@@ -825,31 +816,26 @@ public List<QueryMethod> getQueryMethods() {
825816 private static final class RepositoryInformationCacheKey {
826817
827818 private final String repositoryInterfaceName ;
828- private final long compositionHash ;
819+ private final long fragmentsHash ;
829820
830821 /**
831- * Creates a new {@link RepositoryInformationCacheKey} for the given {@link RepositoryMetadata} and composition .
822+ * Creates a new {@link RepositoryInformationCacheKey} for the given {@link RepositoryMetadata} and fragments .
832823 *
833824 * @param metadata must not be {@literal null}.
834- * @param composition must not be {@literal null}.
825+ * @param fragments must not be {@literal null}.
835826 */
836- public RepositoryInformationCacheKey (RepositoryMetadata metadata , RepositoryComposition composition ) {
827+ public RepositoryInformationCacheKey (RepositoryMetadata metadata , RepositoryFragments fragments ) {
837828
838829 this .repositoryInterfaceName = metadata .getRepositoryInterface ().getName ();
839- this .compositionHash = composition .hashCode ();
840- }
841-
842- public RepositoryInformationCacheKey (String repositoryInterfaceName , long compositionHash ) {
843- this .repositoryInterfaceName = repositoryInterfaceName ;
844- this .compositionHash = compositionHash ;
830+ this .fragmentsHash = fragments .getFragments ().hashCode ();
845831 }
846832
847833 public String getRepositoryInterfaceName () {
848834 return this .repositoryInterfaceName ;
849835 }
850836
851- public long getCompositionHash () {
852- return this .compositionHash ;
837+ public long getFragmentsHash () {
838+ return this .fragmentsHash ;
853839 }
854840
855841 @ Override
@@ -860,7 +846,7 @@ public boolean equals(Object o) {
860846 if (!(o instanceof RepositoryInformationCacheKey that )) {
861847 return false ;
862848 }
863- if (compositionHash != that .compositionHash ) {
849+ if (fragmentsHash != that .fragmentsHash ) {
864850 return false ;
865851 }
866852 return ObjectUtils .nullSafeEquals (repositoryInterfaceName , that .repositoryInterfaceName );
@@ -869,14 +855,14 @@ public boolean equals(Object o) {
869855 @ Override
870856 public int hashCode () {
871857 int result = ObjectUtils .nullSafeHashCode (repositoryInterfaceName );
872- result = 31 * result + ( int ) ( compositionHash ^ ( compositionHash >>> 32 ) );
858+ result = 31 * result + Long . hashCode ( fragmentsHash );
873859 return result ;
874860 }
875861
876862 @ Override
877863 public String toString () {
878864 return "RepositoryFactorySupport.RepositoryInformationCacheKey(repositoryInterfaceName="
879- + this .getRepositoryInterfaceName () + ", compositionHash =" + this .getCompositionHash () + ")" ;
865+ + this .getRepositoryInterfaceName () + ", fragmentsHash =" + this .getFragmentsHash () + ")" ;
880866 }
881867 }
882868
0 commit comments