Skip to content

Commit 86e8079

Browse files
committed
version 0.3.3.0 update
完成乐观锁处理器开发,目前可以将乐观锁动态编译进入类成员
1 parent f32d9cc commit 86e8079

File tree

4 files changed

+158
-12
lines changed

4 files changed

+158
-12
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,7 @@
5555
<tr>
5656
<td>0.3.2.0</td><td>修复读写锁没导入包的BUG;开发乐观锁注解</td><td>2022年1月30日</td>
5757
</tr>
58+
<tr>
59+
<td>0.3.3.0</td><td>完成乐观锁处理器开发,目前可以将乐观锁动态编译进入类成员</td><td>2022年1月30日</td>
60+
</tr>
5861
</table>

pom.xml

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
<dependency>
2626
<groupId>com.sun</groupId>
2727
<artifactId>tools</artifactId>
28-
<version>1.0</version>
28+
<version>1.8.0_292</version>
2929
<scope>system</scope>
3030
<systemPath>${JAVA_HOME}/lib/tools.jar</systemPath>
3131
</dependency>
@@ -93,16 +93,6 @@
9393
<!--Springboot的maven插件-->
9494
<build>
9595
<finalName>${project.artifactId}-${project.version}</finalName>
96-
<!-- <plugins>-->
97-
<!-- <plugin>-->
98-
<!-- <groupId>org.springframework.boot</groupId>-->
99-
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
100-
<!-- <version>2.4.6</version>-->
101-
<!-- <configuration>-->
102-
<!-- <includeSystemScope>true</includeSystemScope>-->
103-
<!-- </configuration>-->
104-
<!-- </plugin>-->
105-
<!-- </plugins>-->
10696
<plugins>
10797

10898
<plugin>
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package org.springframework.lock.processor;
2+
3+
import com.google.auto.service.AutoService;
4+
import com.sun.source.tree.Tree;
5+
import com.sun.tools.javac.api.JavacTrees;
6+
import com.sun.tools.javac.code.Flags;
7+
import com.sun.tools.javac.code.TypeTag;
8+
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
9+
import com.sun.tools.javac.tree.JCTree;
10+
import com.sun.tools.javac.tree.TreeMaker;
11+
import com.sun.tools.javac.tree.TreeTranslator;
12+
import com.sun.tools.javac.util.Context;
13+
import com.sun.tools.javac.util.Names;
14+
15+
import javax.annotation.processing.*;
16+
import javax.lang.model.SourceVersion;
17+
import javax.lang.model.element.Element;
18+
import javax.lang.model.element.ExecutableElement;
19+
import javax.lang.model.element.TypeElement;
20+
import javax.lang.model.type.TypeKind;
21+
import javax.tools.Diagnostic;
22+
import java.util.HashSet;
23+
import java.util.Set;
24+
25+
import static com.sun.tools.javac.util.List.of;
26+
import static com.sun.tools.javac.tree.JCTree.*;
27+
28+
/**
29+
* 乐观锁的处理器,用于将乐观锁编译进类成员
30+
*/
31+
@SupportedAnnotationTypes("org.springframework.lock.annotation.OptimisticLock")
32+
@SupportedSourceVersion(SourceVersion.RELEASE_8)
33+
@AutoService(Processor.class)
34+
public class OptimisticLockProcessor extends AbstractProcessor {
35+
36+
/**
37+
* 编译时输入日志的
38+
*/
39+
private Messager messager;
40+
41+
/**
42+
* 待处理的抽象语法树
43+
*/
44+
private JavacTrees javacTrees;
45+
46+
/**
47+
* 封装了AST节点的一些方法
48+
*/
49+
private TreeMaker treeMaker;
50+
51+
/**
52+
* 提供了创建标识符的方法
53+
*/
54+
private Names names;
55+
56+
/**
57+
* 初始化一些成员变量,方便下面使用
58+
* @param processingEnv 环境
59+
*/
60+
@Override
61+
public synchronized void init(ProcessingEnvironment processingEnv) {
62+
super.init(processingEnv);
63+
this.messager = processingEnv.getMessager();
64+
this.javacTrees = JavacTrees.instance(processingEnv);
65+
Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
66+
this.treeMaker = TreeMaker.instance(context);
67+
this.names = Names.instance(context);
68+
}
69+
70+
/**
71+
* 将乐观锁编译进类的成员变量
72+
* @param annotations 注解
73+
* @param roundEnv 有关当前和以前round的环境信息,可以从这里拿到可以处理的所有元素信息
74+
* @return true——则这些注解已声明并且不要求后续Processor处理它们;false——则这些注解未声明并且可能要求后续 Processor处理它们。
75+
*/
76+
@Override
77+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
78+
for (TypeElement annotation : annotations) {
79+
Set<TypeElement> cls = new HashSet<TypeElement>();
80+
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(annotation);
81+
// 找到都有哪些类里面的方法用到了这个注解
82+
for (Element element : elements) {
83+
ExecutableElement method = (ExecutableElement) element;
84+
TypeElement clz = (TypeElement) method.getEnclosingElement();
85+
messager.printMessage(Diagnostic.Kind.NOTE, "发现需要包含注解" + annotation.getQualifiedName() + "的类" + clz.getQualifiedName());
86+
cls.add(clz);
87+
}
88+
for (TypeElement clz : cls) {
89+
JCTree tree = javacTrees.getTree(clz);
90+
tree.accept(new TreeTranslator() {
91+
@Override
92+
public void visitClassDef(JCTree.JCClassDecl jcClassDecl) {
93+
// 在抽象树中找出所有的变量
94+
boolean foundOptimisticLock = false;
95+
for (JCTree jcTree : jcClassDecl.defs) {
96+
if (jcTree.getKind().equals(Tree.Kind.VARIABLE)) {
97+
JCVariableDecl var = (JCTree.JCVariableDecl) jcTree;
98+
if ("$opLock".equals("" + var.name)) {
99+
// 找到了类中的乐观锁,不修改语法树
100+
messager.printMessage(Diagnostic.Kind.NOTE, "已发现" + clz.getQualifiedName() + "类中的乐观锁" + var.name);
101+
foundOptimisticLock = true;
102+
break;
103+
}
104+
}
105+
}
106+
// 修改语法树
107+
if (!foundOptimisticLock) {
108+
messager.printMessage(Diagnostic.Kind.NOTE, "将为类" + clz.getQualifiedName() + "动态生成乐观锁");
109+
JCVariableDecl lock = makeOptimisticLock(clz);
110+
jcClassDecl.defs = jcClassDecl.defs.append(lock);
111+
}
112+
super.visitClassDef(jcClassDecl);
113+
}
114+
});
115+
}
116+
break;
117+
}
118+
return Boolean.TRUE;
119+
}
120+
121+
/**
122+
* 制作乐观锁
123+
* @return 变量声明
124+
*/
125+
private JCVariableDecl makeOptimisticLock(TypeElement clz){
126+
// 导入包
127+
JCCompilationUnit imports = (JCCompilationUnit) this.javacTrees.getPath(clz).getCompilationUnit();
128+
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));
129+
// 声明变量
130+
JCModifiers modifiers = this.treeMaker.Modifiers(Flags.PRIVATE + Flags.FINAL);
131+
JCVariableDecl var = this.treeMaker.VarDef(
132+
modifiers,
133+
this.names.fromString("$opLock"),
134+
this.memberAccess("java.util.concurrent.atomic.AtomicBoolean"),
135+
this.treeMaker.NewClass(null, of(memberAccess("java.lang.Boolean")), treeMaker.Ident(names.fromString("AtomicBoolean")), of(this.treeMaker.Literal(true)), null)
136+
);
137+
return var;
138+
}
139+
140+
/**
141+
* 制作声明类型
142+
* @param components 声明类型的带包类名
143+
* @return 声明类型
144+
*/
145+
private JCExpression memberAccess(String components) {
146+
String[] componentArray = components.split("\\.");
147+
JCExpression expr = treeMaker.Ident(this.names.fromString(componentArray[0]));
148+
for (int i = 1; i < componentArray.length; i++) {
149+
expr = treeMaker.Select(expr, this.names.fromString(componentArray[i]));
150+
}
151+
return expr;
152+
}
153+
}

src/test/java/example/name/service/BaseService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public String testWriteLock(){
5959
return "testWriteLock 执行结束";
6060
}
6161

62-
// @OptimisticLock
62+
@OptimisticLock
6363
public String testOptimisticLock(){
6464
return "testOptimisticLock 执行结束";
6565
}

0 commit comments

Comments
 (0)