Reputation: 590
Related:
This question is pretty much the same as this, but the answer using BeanFactoryAware
doesn't solve my problem as the created @Bean
s are not @Autowireable.
Requirements:
@ConfigurationProperties
;@Autowire
created beans in application.Example:
Make it possible to declare number of caffeine-based Cache
@Beans
via spring config. Following is implementation based on the accepted answer from the similar question:
First, the boot autoconfiguration module:
@Component
@ConfigurationProperties
@Data
public class Props {
private LocalCacheConf cache = new LocalCacheConf();
@Data
public static class LocalCacheConf {
/**
* List of caches to create, with accompanying configuration.
*/
private List<CacheDef> caches = new ArrayList<>();
@Data
public static class CacheDef {
private String name;
private CaffeineCacheConf properties;
}
@Data
public static class CaffeineCacheConf {
private long maximumSize = -1;
}
}
}
@Configuration
@Slf4j
public class LocalCacheConfig implements BeanFactoryAware {
@Autowired private Props props;
@Setter private BeanFactory beanFactory;
private CaffeineCacheManager localCacheManager;
@PostConstruct
public void configure() {
setCacheManager();
createCaches( props.getCache() );
}
private void createCaches( LocalCacheConf locCacheConf ) {
ConfigurableBeanFactory configurableBeanFactory = (ConfigurableBeanFactory) beanFactory;
for ( CacheDef cacheProps : locCacheConf.getCaches() ) {
Cache cache = createAndConfigureCache(
cacheProps.getName(),
cacheProps.getProperties()
);
configurableBeanFactory.registerSingleton( cacheProps.getName(), cache );
}
}
private Cache createAndConfigureCache( String name, CaffeineCacheConf props ) {
Caffeine<Object, Object> c = Caffeine.newBuilder().recordStats();
if ( props.getMaximumSize() >= 0 ) {
c.maximumSize( props.getMaximumSize() );
}
// can extend config to include additional properties
localCacheManager.setCaffeine( c );
log.info( "building [{}] cache with config: [{}]", name, c.toString() );
return localCacheManager.getCache( name );
}
private void setCacheManager() {
log.info( "creating {}...", "localCacheManager" );
localCacheManager = new CaffeineCacheManager();
( (ConfigurableBeanFactory) beanFactory )
.registerSingleton( "localCacheManager", localCacheManager );
}
}
And finally, the using application would define its caches via configuration (yaml here):
cache:
caches:
- name: c1
properties:
maximumSize: 50
- name: c2
properties:
maximumSize: 5000
This example is based on the answer from the similar question, but the cache @Beans created this way can't be autowired in the application.
Feels like registering bean definitions in ImportBeanDefinitionRegistrar
could work, but don't think beanDefs can be used with Caffeine
instances, as those are created via builder, not property setters.
How could this be implemented?
Upvotes: 1
Views: 710