@Bean(name = {"cachingAttributeRepository", PrincipalResolver.BEAN_NAME_ATTRIBUTE_REPOSITORY})
        @ConditionalOnMissingBean(name = {"cachingAttributeRepository", PrincipalResolver.BEAN_NAME_ATTRIBUTE_REPOSITORY})
        @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
        public PersonAttributeDao cachingAttributeRepository(
            final CasConfigurationProperties casProperties,
            @Qualifier("aggregatingAttributeRepository")
            final PersonAttributeDao aggregatingAttributeRepository) {
            val props = casProperties.getAuthn().getAttributeRepository().getCore();
            if (props.getExpirationTime() <= 0) {
                LOGGER.warn("Attribute repository caching is disabled");
                return aggregatingAttributeRepository;
            }

            val impl = new CachingPersonAttributeDaoImpl();
            impl.setCacheNullResults(false);
            val userinfoCache = Caffeine.newBuilder()
                .maximumSize(props.getMaximumCacheSize())
                .expireAfterWrite(props.getExpirationTime(), TimeUnit.valueOf(props.getExpirationTimeUnit().toUpperCase(Locale.ENGLISH)))
                .build();
            impl.setUserInfoCache((Map) userinfoCache.asMap());
            impl.setCachedPersonAttributesDao(aggregatingAttributeRepository);
            LOGGER.trace("Configured cache expiration policy for attribute sources to be [{}] minute(s)", props.getExpirationTime());
            return impl;
        }
This is {@link CasPersonDirectoryConfiguration}.

@author Misagh Moayyed
@since 5.0.0
support/cas-server-support-person-directory/src/main/java/org/apereo/cas/config/CasPersonDirectoryConfiguration.java