Skip to content

Instantly share code, notes, and snippets.

@kubamarchwicki
Created January 6, 2019 22:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kubamarchwicki/b9968045ee511f37bd36e299aa5ab03d to your computer and use it in GitHub Desktop.
Save kubamarchwicki/b9968045ee511f37bd36e299aa5ab03d to your computer and use it in GitHub Desktop.
Enable Spring Cache for abstract classes in Spring
package com.example.caching;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
import org.springframework.cache.interceptor.CacheResolver;
import org.springframework.cache.interceptor.SimpleCacheResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@SpringBootApplication
public class CacheableAbstractClassApp {
private static Logger logger = LoggerFactory.getLogger(CacheableAbstractClassApp.class);
public static void main(String[] args) {
SpringApplication.run(CacheableAbstractClassApp.class, args);
}
private final Repository<Book> bookRepository;
private final Repository<Author> authorsRepository;
public CacheableAbstractClassApp(Repository<Book> bookRepository, Repository<Author> authorsRepository) {
this.bookRepository = bookRepository;
this.authorsRepository = authorsRepository;
}
@Bean
public CommandLineRunner fetchingBooks() {
return args -> {
logger.info(".... Fetching books");
logger.info("findAll() -->" + bookRepository.findAll());
logger.info("findAll() -->" + bookRepository.findAll());
logger.info("findAll() -->" + bookRepository.findAll());
};
}
@Bean
public CommandLineRunner fetchingAuthors() {
return args -> {
logger.info(".... Fetching authors");
logger.info("findAll() -->" + authorsRepository.findAll());
logger.info("findAll() -->" + authorsRepository.findAll());
logger.info("findAll() -->" + authorsRepository.findAll());
};
}
}
@Configuration
@EnableCaching
class CachingConfiguration extends CachingConfigurerSupport {
final static String CACHE_RESOLVER_NAME = "simpleCacheResolver";
@Bean
@Override
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager();
}
@Bean(CACHE_RESOLVER_NAME)
public CacheResolver cacheResolver(CacheManager cacheManager) {
return new RuntimeCacheResolver(cacheManager);
}
}
class RuntimeCacheResolver
extends SimpleCacheResolver {
protected RuntimeCacheResolver(CacheManager cacheManager) {
super(cacheManager);
}
@Override
protected Collection<String> getCacheNames(CacheOperationInvocationContext<?> context) {
return Arrays.asList(context.getTarget().getClass().getSimpleName());
}
}
interface Dao<T> {
List<T> findAll();
}
abstract class Repository<T> {
protected void simulateSlowService() {
try {
long time = 3000L;
Thread.sleep(time);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
public abstract Dao<T> getDao();
@Cacheable(cacheResolver = "simpleCacheResolver")
public List<T> findAll() {
return getDao().findAll();
}
}
@Component
class SimpleBookRepository extends Repository<Book> {
@Autowired
JdbcTemplate template;
@Override
public Dao<Book> getDao() {
return () -> {
simulateSlowService();
return template.query("SELECT * FROM BOOKS",
(rs, rowNum) -> new Book(rs.getString("ISBN"), rs.getString("TITLE")));
};
}
}
@Component
class SimpleAuthorsRepository extends Repository<Author> {
@Autowired
JdbcTemplate template;
@Override
public Dao<Author> getDao() {
return () -> {
simulateSlowService();
return template.query("SELECT * FROM AUTHORS",
(rs, rowNum) -> new Author(rs.getString("NAME")));
};
}
}
@Data
class Book {
private final String isbn;
private final String title;
}
@Data
class Author {
private final String name;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment