zookeeper分布式锁和切面编程

参考文章

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
@Component
public 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("代码执行中");
}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值