Use spring AOP and annotation implementation methods to check the cache-How far can we go series (46), aopcache-

Source: Internet
Author: User

Use spring AOP and annotation implementation methods to check the cache-How far can we go series (46), aopcache-

Subject:
This code is a common code used in development. It queries the data of a master table in a database. To improve performance, a cache is performed. cache data is obtained for each call, and data is directly returned, no data can be queried from the database to reduce the pressure on the database.

Public Merchant loadCachedMerchant (String merchantId) {String key = this. createCacheKey (merchantId); Merchant merchant = (Merchant) this. memCachedClient. get (key); // first check the cache if (merchant = null) {merchant = this. merchantDao. searchMerchantByMerchantId1 (merchantId); // query the database if (merchant! = Null) {merchant = extraCacheMerchant (merchant); this. memCachedClient. put (key, merchant, 5*60);} return merchant ;}

However, during the initial or development of the project, I cannot plan the services that need to be cached, however, we found that the logic of first caching and then database is common, so we thought of cross-section development to solve this problem.

We can imagine that we can use annotations to provide a separate annotation for those methods that require this caching logic, so that we can find these aspects, that is, the method with this specific annotation, for example @ ServiceCache

The parameters required for this @ ServiceCache annotation include the composition of the cache key and the validity period.

@Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface ServiceCache {    int value() default -1;    int expire() default 60;    ServiceCache.Key key() default ServiceCache.Key.JSON;    String[] includeKeys() default {};    boolean sync() default false;    boolean nullPattern() default true;    public static enum Key {        JSON,        TO_STRING;        private Key() {        }    }}

Here, a sync parameter is added to control synchronous execution. What problems does this synchronization parameter solve? We all understand that the cache is used to solve the problem of frequent database calls. These concurrent calls may cause pressure on the database. In our logic, we should first check the cache, when there are no concurrent requests, the database will be searched. However, in an extreme case, when a large number of requests are concurrently sent, the cache of the judgment logic check will not be found at the same time, that is, if the database data has not been cached, The concurrency will be searched by the database, and the database still has the risk of concurrent calls.

@ Aspectpublic class ServiceCacheAnnotationAspect {private static Logger log = LoggerFactory. getLogger (ServiceCacheAnnotationAspect. class); private ICache serviceCache; private Object syncLock = new Object (); public ServiceCacheAnnotationAspect () {}/*** @ Service or @ Repository is used for class aspect matching and the custom @ ServiceCache ***/@ Around ("(@ within (org. springframework. stereotype. service) |
@ Within (org. springframework. stereotype. Repository ))&&
@ Annotation (com. xiaoka. freework. cache. annotation. serviceCache) ") private Object cacheProcess (ProceedingJoinPoint jp) throws Throwable {Class targetClz = jp. getTarget (). getClass (); String methodName = jp. getSignature (). getName (); if (! (Jp. getSignature () instanceof MethodSignature) {log. warn ("This method interface cannot enable the cache function: {}", jp. getSignature (). toLongString (); return jp. proceed ();} else {MethodSignature methodSign = (MethodSignature) jp. getSignature (); ServiceCache SC = ServiceCacheUtils. single (). findServiceCache (targetClz, methodSign. getMethod (); if (SC = null) {return jp. proceed ();} else {int expire = SC. value ()> = 0? SC. value (): SC. expire (); // get the defined expiration time if (expire> 0) {String cacheKey = ServiceCacheUtils. single (). buildCacheKey (SC, targetClz, methodName, jp. getArgs (); Object rval = null; if (SC. sync () {Object var9 = this. syncLock; synchronized (this. syncLock) {// synchronize rval = this. cacheInvoke (SC, jp, cacheKey, expire); // here we implement our core logic} else {rval = this. cacheInvoke (SC, jp, cacheKey, expire);} return rval insta Nceof ServiceCacheAnnotationAspect. Blank? Null: rval;} else {return jp. proceed () ;}}} private Object cacheInvoke (ServiceCache SC, ProceedingJoinPoint jp, String cacheKey, int expire) throws Throwable {log. debug ("Load from cache for key :{}", cacheKey); Object rval = this. serviceCache. get (cacheKey); if (rval = null) {// The cache does not exist, you need to get it from the database. After the cache is completed, the log.info ("Miss from cache, load backend for key: {} ", cacheKey); rval = jp. proceed (); // execution target method Rval = null & SC. nullPattern ()? ServiceCacheAnnotationAspect. Blank. INST: rval; if (rval! = Null) {this. serviceCache. put (cacheKey, rval, expire) ;}} return rval;} public void setServiceCache (ICache serviceCache) {this. serviceCache = serviceCache; ServiceCacheUtils. single (). setCache (serviceCache);} private static class Blank implements Serializable {private static final long serialVersionUID = 3203712628835590212L; private static final ServiceCacheAnnotationAspect. blank INST = new ServiceCacheAnnotationAspect. blank (); private Blank (){}}}


The actual example is as follows:

@ServiceCache(expire = 600, includeKeys = { "name" })    public CarProvinceEntity selectProvinceByName(String name) {        return commonDao.mapper(CarProvinceEntity.class).source(Source.SLAVE)                        .sql("selectByName").session().selectOne(name);    }

In this way, it is more convenient for developers. Using aop combined with annotations, you can do some aspect work in the project, which has become a part of the underlying framework of many projects, such as the time-consuming computing method, logging, internationalization, and so on.

Links to related knowledge points:

Http://www.cnblogs.com/killbug/p/5271291.html

Http://samter.iteye.com/blog/410618
Http://itindex.net/detail/29812-aop
Http://www.ibm.com/developerworks/cn/java/j-lo-aopi18n/index.html

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.