diff --git a/README.md b/README.md index c1664f5..eaa7f67 100644 --- a/README.md +++ b/README.md @@ -85,4 +85,7 @@ 1.1.0.0新增注解@MakeReadWriteLocks用于对类生成自定义读写锁,其fair属性来自于注解的类下@ReadLock注解或@WriteLock注解的fair属性值2022年2月6日 + +1.2.0.0废弃@MakeReadWriteLocks注解,现在不需要该注解也能正常识别自定义的锁;精简代码,提高编译速度2022年2月6日 + diff --git a/src/main/java/org/springframework/lock/annotation/MakeReadWriteLocks.java b/src/main/java/org/springframework/lock/annotation/MakeReadWriteLocks.java deleted file mode 100644 index dfca0ef..0000000 --- a/src/main/java/org/springframework/lock/annotation/MakeReadWriteLocks.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.springframework.lock.annotation; - -import java.lang.annotation.*; - -/** - * 自动生成读写锁 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -@Documented -public @interface MakeReadWriteLocks { - - /** - * 锁变量的名称,必须是合法变量名,并且不与已有变量声明重合 - * @return 默认无锁变量 - */ - String[] value() default {}; -} diff --git a/src/main/java/org/springframework/lock/annotation/OptimisticLock.java b/src/main/java/org/springframework/lock/annotation/OptimisticLock.java index b88558d..5705790 100644 --- a/src/main/java/org/springframework/lock/annotation/OptimisticLock.java +++ b/src/main/java/org/springframework/lock/annotation/OptimisticLock.java @@ -12,7 +12,7 @@ public @interface OptimisticLock { /** - * 乐观锁变量的名称 + * 乐观锁变量的名称,该变量必须是合法变量名。如果与现有变量冲突,则替换掉现有变量 * @return 默认使用自动生成的锁 */ String value() default ""; diff --git a/src/main/java/org/springframework/lock/annotation/ReadLock.java b/src/main/java/org/springframework/lock/annotation/ReadLock.java index c58d5a7..2ce7820 100644 --- a/src/main/java/org/springframework/lock/annotation/ReadLock.java +++ b/src/main/java/org/springframework/lock/annotation/ReadLock.java @@ -15,13 +15,13 @@ public @interface ReadLock { /** - * 读写锁变量的名称,该变量必须是{@code ReentrantReadWriteLock}类的对象或其子类对象 + * 读写锁变量的名称,该变量必须是合法变量名。如果与现有变量冲突,则替换掉现有变量 * @return 默认使用编译生成的 */ String value() default ""; /** - * 编译时生成的是否公平锁,该属性仅在{@code value}属性保持默认时才生效 + * 是否为公平锁,同一把锁{@code fair}属性只需要写一次即可。如果{@code value}属性与现有变量冲突,则此处的{@code fair}属性将替换掉现有变量的{@code fair}属性 * @return 默认null,如果有自定义值则覆盖默认值 */ BooleanEnum fair() default NULL; diff --git a/src/main/java/org/springframework/lock/annotation/WriteLock.java b/src/main/java/org/springframework/lock/annotation/WriteLock.java index 4f8e779..a0b3e79 100644 --- a/src/main/java/org/springframework/lock/annotation/WriteLock.java +++ b/src/main/java/org/springframework/lock/annotation/WriteLock.java @@ -15,13 +15,13 @@ public @interface WriteLock { /** - * 读写锁变量的名称,该变量必须是{@code ReentrantReadWriteLock}类的对象或其子类对象 + * 读写锁变量的名称,该变量必须是合法变量名。如果与现有变量冲突,则替换掉现有变量 * @return 默认使用编译生成的 */ String value() default ""; /** - * 编译时生成的是否公平锁,该属性仅在{@code value}属性保持默认时才生效 + * 是否为公平锁,同一把锁{@code fair}属性只需要写一次即可。如果{@code value}属性与现有变量冲突,则此处的{@code fair}属性将替换掉现有变量的{@code fair}属性 * @return 默认null,如果有自定义值则覆盖默认值 */ BooleanEnum fair() default NULL; diff --git a/src/main/java/org/springframework/lock/annotation/package-info.java b/src/main/java/org/springframework/lock/annotation/package-info.java index 4822efd..c37189e 100644 --- a/src/main/java/org/springframework/lock/annotation/package-info.java +++ b/src/main/java/org/springframework/lock/annotation/package-info.java @@ -3,6 +3,6 @@ * 每个注解上都有对应的注释,写得很清楚,自己看就可以了,不加以赘述. * 需要注意的是,如果需要使锁注解生效,需要在springboot启动类上添加{@code @EnableSpringLocks}注解 * @author 宗祥瑞 - * @version 1.0.0.0 + * @version 1.2.0.0 */ package org.springframework.lock.annotation; \ No newline at end of file diff --git a/src/main/java/org/springframework/lock/aspect/OptimisticLockAspect.java b/src/main/java/org/springframework/lock/aspect/OptimisticLockAspect.java index cdd5672..e8b8716 100644 --- a/src/main/java/org/springframework/lock/aspect/OptimisticLockAspect.java +++ b/src/main/java/org/springframework/lock/aspect/OptimisticLockAspect.java @@ -161,6 +161,7 @@ private static Thread findThread(long threadId) { * @param waitTime 最长等待时长 * @param pollingTime 轮询周期 * @return 是否获得锁 + * @throws InterruptedException 中断异常 */ private boolean tryLock(AtomicLong lock, long waitTime, long pollingTime) throws InterruptedException { long startWaitTime = System.currentTimeMillis(); diff --git a/src/main/java/org/springframework/lock/aspect/package-info.java b/src/main/java/org/springframework/lock/aspect/package-info.java index bae4f54..e06378f 100644 --- a/src/main/java/org/springframework/lock/aspect/package-info.java +++ b/src/main/java/org/springframework/lock/aspect/package-info.java @@ -3,6 +3,6 @@ * 每个切面都有注释,没什么好说的,不加以赘述. * 切面这部分需要托管到spring容器中去执行. * @author 宗祥瑞 - * @version 1.0.0.0 + * @version 1.2.0.0 */ package org.springframework.lock.aspect; \ No newline at end of file diff --git a/src/main/java/org/springframework/lock/enumeration/package-info.java b/src/main/java/org/springframework/lock/enumeration/package-info.java index f1eac91..40c181b 100644 --- a/src/main/java/org/springframework/lock/enumeration/package-info.java +++ b/src/main/java/org/springframework/lock/enumeration/package-info.java @@ -1,7 +1,7 @@ /** * 这是关于枚举类型的包. * 写得很清楚,直接看代码就好了. - * @version 1.0.0.0 + * @version 1.2.0.0 * @author 宗祥瑞 */ package org.springframework.lock.enumeration; \ No newline at end of file diff --git a/src/main/java/org/springframework/lock/processor/OptimisticLockProcessor.java b/src/main/java/org/springframework/lock/processor/OptimisticLockProcessor.java index 972ccda..21cdc14 100644 --- a/src/main/java/org/springframework/lock/processor/OptimisticLockProcessor.java +++ b/src/main/java/org/springframework/lock/processor/OptimisticLockProcessor.java @@ -80,7 +80,6 @@ public synchronized void init(ProcessingEnvironment processingEnv) { @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { for (TypeElement annotation : annotations) { - Set cls = new HashSet(); Set elements = roundEnv.getElementsAnnotatedWith(annotation); // 找到都有哪些类里面的方法用到了这个注解 Map> map = new HashMap>(); @@ -89,11 +88,10 @@ public boolean process(Set annotations, RoundEnvironment String varName = method.getAnnotation(OptimisticLock.class).value(); TypeElement clz = (TypeElement) method.getEnclosingElement(); messager.printMessage(Diagnostic.Kind.NOTE, "发现需要包含注解" + annotation.getQualifiedName() + "的类" + clz.getQualifiedName()); - cls.add(clz); map.computeIfAbsent(clz, k -> nil()); map.computeIfPresent(clz, (k, v) -> v.append(varName)); } - for (TypeElement clz : cls) { + for (TypeElement clz : map.keySet()) { List lockNames = map.get(clz); if (lockNames.contains("")){ lockNames = List.filter(lockNames, ""); @@ -112,7 +110,7 @@ public void visitClassDef(JCTree.JCClassDecl jcClassDecl) { JCVariableDecl var = (JCVariableDecl) jcTree; if (locks.contains("" + var.name)) { // 找到了类中的乐观锁,舍弃掉 - messager.printMessage(Diagnostic.Kind.NOTE, "已发现" + clz.getQualifiedName() + "类中的乐观锁" + var.name); + messager.printMessage(Diagnostic.Kind.WARNING, "已发现" + clz.getQualifiedName() + "类中的同名变量" + var.name + ", 将进行替换"); }else{ tree = tree.append(jcTree); } diff --git a/src/main/java/org/springframework/lock/processor/ReadWriteLockProcessor.java b/src/main/java/org/springframework/lock/processor/ReadWriteLockProcessor.java index 9b669ab..606ffe3 100644 --- a/src/main/java/org/springframework/lock/processor/ReadWriteLockProcessor.java +++ b/src/main/java/org/springframework/lock/processor/ReadWriteLockProcessor.java @@ -9,9 +9,9 @@ import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.tree.TreeTranslator; import com.sun.tools.javac.util.*; -import org.springframework.lock.annotation.MakeReadWriteLocks; import org.springframework.lock.annotation.ReadLock; import org.springframework.lock.annotation.WriteLock; +import org.springframework.util.StringUtils; import javax.annotation.processing.*; import javax.lang.model.SourceVersion; @@ -83,43 +83,36 @@ public synchronized void init(ProcessingEnvironment processingEnv) { public boolean process(Set annotations, RoundEnvironment roundEnv) { if (annotations.size() == 0) return Boolean.TRUE; - Set cls = new HashSet(); - Map> map = new HashMap>(); + Map> lockProperties = new HashMap>(); for (TypeElement annotation : annotations) { Set elements = roundEnv.getElementsAnnotatedWith(annotation); // 找到都有哪些类里面的方法用到了这个注解 for (Element element : elements) { ExecutableElement method = (ExecutableElement) element; TypeElement clz = (TypeElement) method.getEnclosingElement(); - messager.printMessage(Diagnostic.Kind.NOTE, "发现需要包含注解" + annotation.getQualifiedName() + "的类" + clz.getQualifiedName()); + lockProperties.putIfAbsent(clz, new HashMap()); + messager.printMessage(Diagnostic.Kind.NOTE, "发现包含注解" + annotation.getQualifiedName() + "的类" + clz.getQualifiedName()); Boolean isFair = null; + String lockName = null; if (("" + annotation).equals("org.springframework.lock.annotation.ReadLock")) { // 如果方法注解了读锁 isFair = method.getAnnotation(ReadLock.class).fair().getValue(); + lockName = method.getAnnotation(ReadLock.class).value(); } if (("" + annotation).equals("org.springframework.lock.annotation.WriteLock")) { // 如果方法注解了写锁 isFair = method.getAnnotation(WriteLock.class).fair().getValue(); + lockName = method.getAnnotation(WriteLock.class).value(); } - if (isFair != null) { - Boolean finalIsFair = isFair; - map.put(clz, new HashMap(){{ - put("fair", finalIsFair); - }}); - }else { - if (map.get(clz) == null || map.get(clz).get("fair") == null){ - map.put(clz, new HashMap(){{ - put("fair", null); - }}); - } - } - cls.add(clz); + if (!StringUtils.hasText(lockName)) + lockName = "$lock"; + if (isFair != null) + lockProperties.get(clz).put(lockName, isFair); + lockProperties.get(clz).putIfAbsent(lockName, null); } } // 对每一个涉及到的类添加锁成员 - for (TypeElement clz : cls) { - MakeReadWriteLocks makeReadWriteLocks = clz.getAnnotation(MakeReadWriteLocks.class); - String[] makeLocks = makeReadWriteLocks != null ? makeReadWriteLocks.value() : new String[]{}; + for (TypeElement clz : lockProperties.keySet()) { JCTree tree = javacTrees.getTree(clz); tree.accept(new TreeTranslator() { @Override @@ -127,29 +120,25 @@ public void visitClassDef(JCClassDecl jcClassDecl) { // 在抽象树中过滤掉已有的的变量 List trees = nil(); for (JCTree x : jcClassDecl.defs) { - if (x.getKind().equals(Kind.VARIABLE) && ("$lock".equals("" + ((JCVariableDecl) x).name) || "$readLock".equals("" + ((JCVariableDecl) x).name) || "$writeLock".equals("" + ((JCVariableDecl) x).name))) + if (x.getKind().equals(Kind.VARIABLE) && lockProperties.get(clz).containsKey("" + ((JCVariableDecl) x).name)) messager.printMessage(Diagnostic.Kind.WARNING, "已删除变量声明" + ((JCVariableDecl) x).name + ", 因为这个变量与生成的锁变量重名了"); else trees = trees.append(x); } jcClassDecl.defs = trees; - // 生成$读写锁 - messager.printMessage(Diagnostic.Kind.NOTE, "将为类" + clz.getQualifiedName() + "动态生成读写锁$lock"); - JCVariableDecl lock = makeReadWriteLock(clz, "$lock", map.get(clz)); - jcClassDecl.defs = jcClassDecl.defs.append(lock); - messager.printMessage(Diagnostic.Kind.NOTE, "将为类" + clz.getQualifiedName() + "动态生成读锁$readLock"); - JCVariableDecl readLock = makeReadLock(clz, "$readLock"); - jcClassDecl.defs = jcClassDecl.defs.append(readLock); - messager.printMessage(Diagnostic.Kind.NOTE, "将为类" + clz.getQualifiedName() + "动态生成写锁$writeLock"); - JCVariableDecl writeLock = makeWriteLock(clz, "$writeLock"); - jcClassDecl.defs = jcClassDecl.defs.append(writeLock); - // 生成make读写锁 - for (String makeLock : makeLocks) { - if (makeLock.length() == 0) - continue; - messager.printMessage(Diagnostic.Kind.NOTE, "将为类" + clz.getQualifiedName() + "动态生成读写锁" + makeLock); - JCVariableDecl make = makeReadWriteLock(clz, makeLock, map.get(clz)); - jcClassDecl.defs = jcClassDecl.defs.append(make); + // 生成读写锁 + for (String varName : lockProperties.get(clz).keySet()) { + messager.printMessage(Diagnostic.Kind.NOTE, "将为类" + clz.getQualifiedName() + "动态生成读写锁" + varName); + JCVariableDecl lock = makeReadWriteLock(clz, varName, lockProperties.get(clz).get(varName)); + jcClassDecl.defs = jcClassDecl.defs.prepend(lock); + if ("$lock".equals(varName)){ + messager.printMessage(Diagnostic.Kind.NOTE, "将为类" + clz.getQualifiedName() + "动态生成读锁$readLock"); + JCVariableDecl readLock = makeReadLock(clz, "$readLock"); + jcClassDecl.defs = jcClassDecl.defs.append(readLock); + messager.printMessage(Diagnostic.Kind.NOTE, "将为类" + clz.getQualifiedName() + "动态生成写锁$writeLock"); + JCVariableDecl writeLock = makeWriteLock(clz, "$writeLock"); + jcClassDecl.defs = jcClassDecl.defs.append(writeLock); + } } super.visitClassDef(jcClassDecl); @@ -163,26 +152,26 @@ public void visitClassDef(JCClassDecl jcClassDecl) { * 制作读写锁 * @param clz 要添加锁的类 * @param lockName 变量名称 - * @param properties 注解的属性 + * @param isFair 是否公平锁 * @return 变量声明 */ - private JCVariableDecl makeReadWriteLock(TypeElement clz, String lockName, Map properties) { + private JCVariableDecl makeReadWriteLock(TypeElement clz, String lockName, Boolean isFair) { // 导入包 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.locks")), this.names.fromString("ReentrantReadWriteLock")), false)); // 声明变量 JCModifiers modifiers = this.treeMaker.Modifiers(Flags.PRIVATE + Flags.FINAL); - if (properties.get("fair") != null) + if (isFair != null) return this.treeMaker.VarDef( modifiers, this.names.fromString(lockName), this.memberAccess("java.util.concurrent.locks.ReentrantReadWriteLock"), - this.treeMaker.NewClass(null, of(memberAccess("java.lang.Boolean")), treeMaker.Ident(names.fromString("ReentrantReadWriteLock")), of(this.treeMaker.Literal(properties.get("fair"))), null) + this.treeMaker.NewClass(null, of(memberAccess("java.lang.Boolean")), treeMaker.Ident(names.fromString("ReentrantReadWriteLock")), of(this.treeMaker.Literal(isFair)), null) ); else return this.treeMaker.VarDef( modifiers, - this.names.fromString("$lock"), + this.names.fromString(lockName), this.memberAccess("java.util.concurrent.locks.ReentrantReadWriteLock"), this.treeMaker.NewClass(null, nil(), treeMaker.Ident(names.fromString("ReentrantReadWriteLock")), nil(), null) ); diff --git a/src/main/java/org/springframework/lock/processor/package-info.java b/src/main/java/org/springframework/lock/processor/package-info.java index 31cc0c4..7a7d6c5 100644 --- a/src/main/java/org/springframework/lock/processor/package-info.java +++ b/src/main/java/org/springframework/lock/processor/package-info.java @@ -4,6 +4,6 @@ * 它的原理与lombok有些许类似,但代码风格比lombok更好理解,一看就懂 * 每个处理器都写了注释,写得都很清楚,不加以赘述 * @author 宗祥瑞 - * @version 1.0.0.0 + * @version 1.2.0.0 */ package org.springframework.lock.processor; \ No newline at end of file diff --git a/src/main/java/org/springframework/lock/timer/package-info.java b/src/main/java/org/springframework/lock/timer/package-info.java index d4ed58c..a9fcbfb 100644 --- a/src/main/java/org/springframework/lock/timer/package-info.java +++ b/src/main/java/org/springframework/lock/timer/package-info.java @@ -3,6 +3,6 @@ * 意思就是在多长时间后执行什么功能,或者要求每过多长时间执行什么功能. * java不能多继承,所以用内部类来实现 * @author 宗祥瑞 - * @version 1.0.0.0 + * @version 1.2.0.0 */ package org.springframework.lock.timer; \ No newline at end of file diff --git a/src/test/java/example/name/service/BaseService.java b/src/test/java/example/name/service/BaseService.java index 69333d4..356f236 100644 --- a/src/test/java/example/name/service/BaseService.java +++ b/src/test/java/example/name/service/BaseService.java @@ -9,11 +9,6 @@ @Service -@MakeReadWriteLocks({ - "myLock1", - "myLock2", - "myLock3" -}) public class BaseService { private static final Log LOGGER = LogFactory.getLog(BaseService.class); @@ -102,10 +97,11 @@ public String testOptimisticLock2(){ return "testOptimisticLock2 执行结束"; } - @ReadLock("myLock1") + @ReadLock(value = "myLock1", fair = FALSE) public String testMakeLockRead(){ String name = Thread.currentThread().getName(); LOGGER.info(name + "开始执行"); +// System.out.println("" + myLock1.isFair()); try { Thread.sleep(5000); } catch (InterruptedException e) {