之前实现了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
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
最新评论