Skip to content

Commit

Permalink
version 0.4.0.0 update
Browse files Browse the repository at this point in the history
完成乐观锁开发。目前有互斥锁、读写锁、乐观锁,均已测试可用
  • Loading branch information
ZongXR committed Jan 30, 2022
1 parent 86e8079 commit ae0a1c2
Show file tree
Hide file tree
Showing 14 changed files with 104 additions and 15 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,7 @@
<tr>
<td>0.3.3.0</td><td>完成乐观锁处理器开发,目前可以将乐观锁动态编译进入类成员</td><td>2022年1月30日</td>
</tr>
<tr>
<td>0.4.0.0</td><td>完成乐观锁开发。目前有互斥锁、读写锁、乐观锁,均已测试可用</td><td>2022年1月30日</td>
</tr>
</table>
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;
import org.springframework.lock.aspect.OptimisticLockAspect;
import org.springframework.lock.aspect.ReadLockAspect;
import org.springframework.lock.aspect.SynchronizedAspect;
import org.springframework.lock.aspect.WriteLockAspect;
Expand All @@ -14,7 +15,8 @@
@Import({
SynchronizedAspect.class,
ReadLockAspect.class,
WriteLockAspect.class
WriteLockAspect.class,
OptimisticLockAspect.class
})
@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)
@Retention(RetentionPolicy.RUNTIME)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
public @interface OptimisticLock {

/**
* 乐观锁忙等待时间
* 乐观锁忙等待毫秒数
* @return 乐观锁忙等待时间
*/
long value() default 500L;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.springframework.lock.annotation;

import org.springframework.core.annotation.AliasFor;

import java.lang.annotation.*;

/**
Expand All @@ -13,7 +11,7 @@
public @interface Synchronized {

/**
* 用来当作锁的成员变量名,默认使用当前类的字节码当作锁,同lock
* 用来当作锁的成员变量名,默认使用当前类的字节码当作锁
* @return 锁对象
*/
String value() default "";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* 这个包包含了该框架的全部注解.
* 每个注解上都有对应的注释,写得很清楚,自己看就可以了,不加以赘述.
* 需要注意的是,如果需要使锁注解生效,需要在springboot启动类上添加{@code @EnableSpringLocks}注解
* @author 宗祥瑞
* @version 0.5.0.0
*/
package org.springframework.lock.annotation;
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.lock.annotation.OptimisticLock;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.concurrent.atomic.AtomicBoolean;

import static java.lang.Thread.sleep;

/**
* 乐观锁的切面
Expand All @@ -25,8 +33,48 @@ public class OptimisticLockAspect {
*/
@Around("@annotation(org.springframework.lock.annotation.OptimisticLock)")
public Object aroundOptimisticLock(ProceedingJoinPoint jp) throws Throwable {
Object result = jp.proceed();
Object obj = jp.getTarget();
Class<?> clz = obj.getClass();
// 获取等待时长,默认500毫秒
long waitTime = 500L;
MethodSignature signature = (MethodSignature) jp.getSignature();
Method method = signature.getMethod();
if (method != null) {
OptimisticLock annotation = method.getAnnotation(OptimisticLock.class);
if (annotation != null) {
waitTime = annotation.value();
}
}
// 获取锁对象
AtomicBoolean lock = null;
for (Field field : clz.getDeclaredFields()) {
if ("$opLock".equals(field.getName())){
field.setAccessible(true);
Object unknownLock = field.get(obj);
lock = (AtomicBoolean) unknownLock;
}
}
Object result = null;
if (lock != null){
while (true){
if (lock.compareAndSet(true, false))
// 拿到了锁
break;
else
// 如果没拿到锁就忙等待
sleep(waitTime);
}
try {
LOGGER.info(clz.getSimpleName() + "获得乐观锁");
result = jp.proceed();
LOGGER.info(clz.getSimpleName() + "释放乐观锁");
}finally {
lock.set(true);
}
}else{
LOGGER.warn(clz.getSimpleName() + "生成乐观锁失败,未能加锁");
result = jp.proceed();
}
return result;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.boot.SpringApplication;
import org.springframework.lock.annotation.Synchronized;

import java.lang.reflect.Field;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* 这个包存放了注解对应的切面,用来做动态代理.
* 每个切面都有注释,没什么好说的,不加以赘述.
* 切面这部分需要托管到spring容器中去执行.
* @author 宗祥瑞
* @version 0.5.0.0
*/
package org.springframework.lock.aspect;
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.sun.source.tree.Tree;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.TypeTag;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
Expand All @@ -17,7 +16,6 @@
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeKind;
import javax.tools.Diagnostic;
import java.util.HashSet;
import java.util.Set;
Expand Down Expand Up @@ -120,14 +118,15 @@ public void visitClassDef(JCTree.JCClassDecl jcClassDecl) {

/**
* 制作乐观锁
* @param clz 要添加锁的类
* @return 变量声明
*/
private JCVariableDecl makeOptimisticLock(TypeElement clz){
// 导入包
JCCompilationUnit imports = (JCCompilationUnit) this.javacTrees.getPath(clz).getCompilationUnit();
imports.defs = imports.defs.append(this.treeMaker.Import(this.treeMaker.Select(this.treeMaker.Ident(names.fromString("java.util.concurrent.atomic")), this.names.fromString("AtomicBoolean")), false));
// 声明变量
JCModifiers modifiers = this.treeMaker.Modifiers(Flags.PRIVATE + Flags.FINAL);
JCModifiers modifiers = this.treeMaker.Modifiers(Flags.PRIVATE + Flags.VOLATILE);
JCVariableDecl var = this.treeMaker.VarDef(
modifiers,
this.names.fromString("$opLock"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import com.sun.source.tree.Tree;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
Expand All @@ -16,12 +15,10 @@
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import static com.sun.tools.javac.tree.JCTree.*;
import static com.sun.tools.javac.util.List.nil;
Expand Down Expand Up @@ -133,6 +130,7 @@ public void visitClassDef(JCTree.JCClassDecl jcClassDecl) {

/**
* 制作读写锁
* @param clz 要添加锁的类
* @return 变量声明
*/
private JCVariableDecl makeReadWriteLock(TypeElement clz){
Expand All @@ -152,6 +150,7 @@ private JCVariableDecl makeReadWriteLock(TypeElement clz){

/**
* 制作读锁
* @param clz 要添加锁的类
* @return 变量声明
*/
private JCVariableDecl makeReadLock(TypeElement clz){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ public void visitClassDef(JCTree.JCClassDecl jcClassDecl) {

/**
* 制作读写锁
* @param clz 要添加锁的类
* @return 读写锁变量声明
*/
private JCTree.JCVariableDecl makeReadWriteLock(TypeElement clz){
Expand All @@ -149,6 +150,7 @@ private JCTree.JCVariableDecl makeReadWriteLock(TypeElement clz){

/**
* 制作写锁
* @param clz 要添加锁的类
* @return 写锁变量声明
*/
private JCTree.JCVariableDecl makeWriteLock(TypeElement clz){
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* 这个包才是本项目的精华,存储了注解的处理器.
* 这些处理器的作用是将锁对象动态编译进入对应的类,使之成为类的成员.
* 它的原理与lombok有些许类似,但代码风格比lombok更好理解,一看就懂
* 每个处理器都写了注释,写得都很清楚,不加以赘述
* @author 宗祥瑞
* @version 0.5.0.0
*/
package org.springframework.lock.processor;
7 changes: 7 additions & 0 deletions src/test/java/example/name/controller/BaseController.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,11 @@ public String testWriteLock(){
String result = this.baseService.testWriteLock();
return result;
}

@RequestMapping(value = "/testOptimisticLock", method = RequestMethod.GET)
@ResponseBody
public String testOptimisticLock(){
String result = this.baseService.testOptimisticLock();
return result;
}
}
8 changes: 8 additions & 0 deletions src/test/java/example/name/service/BaseService.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ public String testWriteLock(){

@OptimisticLock
public String testOptimisticLock(){
String name = Thread.currentThread().getName();
LOGGER.info(name + "开始执行");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LOGGER.info(name + "执行结束");
return "testOptimisticLock 执行结束";
}
}

0 comments on commit ae0a1c2

Please sign in to comment.