zookeeper分布式锁和切面编程_从心归零的博客-CSDN博客 - 这个锁与解锁的逻辑有问题 - 但有参考意义

参考文章

zookeeper分布式锁

使用切面注解编程实现redis模糊删除数据之二使用spel表达式

之前实现了zookeeper分布式锁,但是使用的时候比较麻烦,还要try{}catch{}包住要加锁的代码,就像这样

DistributedLock dlock = DistributedLockFactory.createLock(lockstr);dlock.lock();try {    process();    dlock.unlock();}catch (Exception e) {    dlock.unlock();    throw e;}

这无疑是非常麻烦的,所以结合之前使用@CacheRemove清除缓存的经验,我尝试使用切面编程在service层上加锁。

import java.io.IOException;import java.io.InputStream;import java.util.Properties;public class DistributedLockFactory {    private static String serverList;    static {        try {            InputStream is = DistributedLockFactory.class.getClassLoader().getResourceAsStream("application.properties");            Properties property = new Properties();            property.load(is);            serverList = property.getProperty("regCenter.serverList");        } catch (IOException e) {            e.printStackTrace();        }    }    public static DistributedLock createLock(String lockName) {        return new DistributedLock(serverList, lockName);    }}
import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target; @Target({ java.lang.annotation.ElementType.METHOD })@Retention(RetentionPolicy.RUNTIME)public @interface ZookeeperLock {    String value();}
import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern; import javax.annotation.Resource; import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.core.LocalVariableTableParameterNameDiscoverer;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.expression.ExpressionParser;import org.springframework.expression.spel.standard.SpelExpressionParser;import org.springframework.expression.spel.support.StandardEvaluationContext;import org.springframework.stereotype.Component; import com.kq.highnet2.framework.base.common.annotation.ZookeeperLock;import com.kq.highnet2.framework.base.common.lock.DistributedLock;import com.kq.highnet2.framework.base.common.lock.DistributedLockFactory; @Aspect@Componentpublic class ZookeeperLockAspect {    Logger logger=LoggerFactory.getLogger(this.getClass());    @Resource(name = "redisTemplate")     RedisTemplate<String, String> redis;    @Pointcut(value = "(execution(* *.*(..)) && "//截获标有@ZookeeperLock的方法            + "@annotation(com.kq.highnet2.framework.base.common.annotation.ZookeeperLock))")    private void pointcut() {}    @Around(value = "pointcut()")//切面在方法返回值之后    private Object process(ProceedingJoinPoint joinPoint) throws Throwable{        MethodSignature signature = (MethodSignature) joinPoint.getSignature();        Object[] args = joinPoint.getArgs();//切面方法的参数        Method method = signature.getMethod();//切面方法        ZookeeperLock zookeeperLock = method.getAnnotation(ZookeeperLock.class);//获得注解        String value = zookeeperLock.value();//获取锁值的表达式        String lockKey = parseKey(value, method, args);        DistributedLock lock = DistributedLockFactory.createLock(lockKey);        Object proceed = null;        if(lock !=null) {            lock.lock();            try {                proceed = joinPoint.proceed();//执行代码                lock.unlock();            } catch (Throwable e) {                lock.unlock();                logger.error(e.getMessage(), e);                throw e;            }        }else {            try {                proceed = joinPoint.proceed();            } catch (Throwable e) {                logger.error(e.getMessage(), e);                throw e;            }        }        return proceed;    }    /**      *    key 定义在注解上,支持SPEL表达式      * @param pjp      * @return      */      private String parseKey(String key,Method method,Object [] args){                   //获取被拦截方法参数名列表(使用Spring支持类库)          LocalVariableTableParameterNameDiscoverer u =                 new LocalVariableTableParameterNameDiscoverer();            String [] paraNameArr=u.getParameterNames(method);                    //使用SPEL进行key的解析          ExpressionParser parser = new SpelExpressionParser();           //SPEL上下文          StandardEvaluationContext context = new StandardEvaluationContext();          //把方法参数放入SPEL上下文中          for(int i=0;i<paraNameArr.length;i++){              context.setVariable(paraNameArr[i], args[i]);          }         List<String> pList = descFormat(key);//获取#p0这样的表达式        //将p0作为参数放入SPEL上下文中        for(String p:pList) {            context.setVariable(p.substring(1), args[Integer.valueOf(p.substring(2))]);        }        return parser.parseExpression(key).getValue(context,String.class);      }     /**     * 提取出#p[数字]这样的表达式     * @param desc     * @return     */    private static List<String> descFormat(String desc){          List<String> list = new ArrayList<>();          Pattern pattern = Pattern.compile("#p[0-9]+");           Matcher matcher = pattern.matcher(desc);           while(matcher.find()){               String t = matcher.group(0);               list.add(t);          }          return list;      }}

DistributedLock 锁的具体实现代码在链接里面有。

然后使用zookeeper分布式锁就只要这样就可以用了

@ZookeeperLock(value="'process'+#companyId")public void process(String userId, String companyId) {    System.out.println("代码执行中");}

是不是就方便多了?虽然只不过是把过去的知识拼凑组合一下而已。。


原网址: 访问
创建于: 2020-12-03 18:20:40
目录: default
标签: 无

请先后发表评论
  • 最新评论
  • 总共0条评论