Spring AOP 实践(四)利用annotation实现声明式服务

来源:互联网 发布:solr remove node 编辑:程序博客网 时间:2024/06/03 17:26

上一篇中说到Spring AOP的一个重要作用是提供声明式企业服务,比如著名的声明式事务处理。

声明式企业服务真的很诱人,可以少写很多代码啊!就好像一句魔法就可以搞定一切。

AOP中可以用annotation来作为切入点的判断条件,比如@Transactional作为切入点,凡是声明了这个注解的方法都会被应用到事务处理的advice。今天我要用annotation和AOP来实现缓存的读取和存储,即在访问目标方法前先判断是否有缓存,有则返回,无则调用目标方法,在返回前存储缓存。

先来定义Annotation:

import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface CacheRetrive {String cacheName() default "";String key();}


再定义一个消除缓存的注解:

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface CacheClear {String cacheName() default "";String[] keys();}
不同的是keys是个数组,即可以清楚多个缓存项。


这是一个在保留到运行时的注解,目标对象是方法。有两个参数,一个是Cache的名字,cacheName,在这篇中不打算使用这个参数,给它一个默认值,否则不传值会报错。另外一个参数是key,就是要处理的缓存项目的key。

Aspect的定义:

@Aspect@Component public class RequestCacheAspect {private static Logger logger = Logger.getRootLogger();@Autowiredprivate EhcacheStorageManager cacheManager;@Around(value="execution(* com.viking.renting.service.*.*(..)) && @annotation(cacheRetrive)")public Object retriveFromCache(ProceedingJoinPoint pjp, CacheRetrive cacheRetrive) throws Throwable {String cacheKey = cacheRetrive.key();Object cacheValue = cacheManager.retrive(cacheKey);if(cacheValue != null) {logger.info("return from cache, key:" + cacheKey);return cacheValue;}Object retVal = pjp.proceed();cacheManager.save(cacheKey, retVal);logger.info("save to cache, key:" + cacheKey);return retVal;}@After(value="execution(* com.viking.renting.service.*.*(..)) && @annotation(cacheClear)")public void retriveFromCache(CacheClear cacheClear) throws Throwable {String[] keys = cacheClear.keys();for(String key: keys) {cacheManager.remove(key);logger.info("remove from cache, key:" + key);}}}
从上面的代码可以看出注解的使用非常方便,可以直接把注解当作参数传进这个方法。第一个方法使用了@Around,就跟自己写个代理类的方法一样,不同的是这个方法可以应用到多个方法上,而我们只需要写一遍。这就是抽象的好处,把相同的事情抽象出来,只做一遍。第二个方法用了@After,在方法执行完成后调用清楚缓存的方法。下面是具体的调用:

<span style="white-space:pre"></span>@Transactional@CacheClear(keys="users_all")public User saveUser(User user)  {....}

@Transactional(readOnly = true)@CacheRetrive(key="users_all")public List<UserTableDataDTO> fetchUsers() {return userDao.findUsers();}

在新增,修改和删除的方法上调用清除缓存,而在查询方法上调用@CacheRetrive。

这个注解放在DAO层是最好的。这只是一个简单的实现,更复杂的功能也是可以实现的。


0 0
原创粉丝点击