前言
项目中为了提高系统响应速度经常把热数据存入缓存中如redis,memcached中。本文介绍一种使用的项目启动加载缓存的方法
基本配置
1.思路
应用启动时加载缓存常用的方法有:
- 编写linstener监听应用启动
- Bean实现InitializingBean接口,并实现afterPropertiesSet()方法
- 在Bean的init-method中进行逻辑代码编写
- 。。。。。
2.相关配置
本文采用实现InitializingBean接口,并实现afterPropertiesSet()方法的方式。
spring初始化bean的时候,如果bean实现了InitializingBean接口,会自动调用afterPropertiesSet方法,并且afterPropertiesSet方法优先于init-method方法执行
可参考Spring AbstractAutowireCapableBeanFactory中的实现
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
boolean isInitializingBean = bean instanceof InitializingBean;
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean)bean).afterPropertiesSet();
return null;
}
}, this.getAccessControlContext());
} catch (PrivilegedActionException var6) {
throw var6.getException();
}
} else {
((InitializingBean)bean).afterPropertiesSet();
}
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && (!isInitializingBean || !"afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
this.invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
3.代码实现
为了代码的可用性,设计CacheInterface接口
public interface CacheInterface {
/**
* 实现接口在应用启动时加载热数据
*
* @return
*/
boolean loadCache();
boolean deleteCache();
}
加载热数据时实现CacheInterface接口
@Service
public class DemoLoadCache implements CacheInterface {
@Override
public boolean loadCache() {
//TODO 从关系型数据库中查询相关的数据并存储到缓存中。
return true;
}
@Override
public boolean deleteCache() {
return false;
}
}
将所有实现CacheInterface接口的加载热数据类注入到处理类中,实际应用中考虑使用线程池。
@Service
public class CacheLoadService implements Runnable, InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(CacheLoadService.class);
@Autowired
private List<CacheInterface> cacheInterfaceList;
@Override
public void run() {
logger.info("start load cache");
long start = System.currentTimeMillis();
if (cacheInterfaceList != null && cacheInterfaceList.size() > 0) {
for (CacheInterface cacheInterface : cacheInterfaceList) {
cacheInterface.loadCache();
}
}
long end = System.currentTimeMillis();
logger.info("load cache finished in {}秒 ", (end - start) / 1000);
}
@Override
public void afterPropertiesSet() throws Exception {
Thread t = new Thread(this);
t.start();
}
}
Spring应用启动的时候,调用CacheLoadService中afterPropertiesSet方法启动线程加载热数据。
结尾
实际应用中考虑真是场景考虑加载数据的方式。对热数据的增删改也要同步到缓存中。