Skip to content

Commit 867c235

Browse files
committed
version 0.3.0.0 update
完成读写锁开发,通过测试确定可用
1 parent beed4b2 commit 867c235

File tree

8 files changed

+254
-10
lines changed

8 files changed

+254
-10
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,7 @@
4343
<tr>
4444
<td>0.2.2.1</td><td>修复读锁逻辑BUG</td><td>2022年1月28日</td>
4545
</tr>
46+
<tr>
47+
<td>0.3.0.0</td><td>完成读写锁开发,通过测试确定可用</td><td>2022年1月29日</td>
48+
</tr>
4649
</table>

pom.xml

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,22 @@
5757
<groupId>org.springframework.boot</groupId>
5858
<artifactId>spring-boot-configuration-processor</artifactId>
5959
<optional>true</optional>
60+
<scope>test</scope>
6061
</dependency>
6162
<dependency>
6263
<groupId>org.springframework.boot</groupId>
6364
<artifactId>spring-boot-actuator</artifactId>
65+
<scope>test</scope>
6466
</dependency>
6567
<dependency>
6668
<groupId>org.springframework.boot</groupId>
6769
<artifactId>spring-boot-autoconfigure</artifactId>
70+
<scope>test</scope>
6871
</dependency>
6972
<dependency>
7073
<groupId>org.springframework.boot</groupId>
7174
<artifactId>spring-boot-starter-web</artifactId>
75+
<scope>test</scope>
7276
</dependency>
7377
<dependency>
7478
<groupId>org.springframework.boot</groupId>
@@ -89,14 +93,50 @@
8993
<!--Springboot的maven插件-->
9094
<build>
9195
<finalName>${project.artifactId}</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>-->
92106
<plugins>
107+
108+
<plugin>
109+
<groupId>org.apache.maven.plugins</groupId>
110+
<artifactId>maven-compiler-plugin</artifactId>
111+
<configuration>
112+
<source>1.8</source>
113+
<target>1.8</target>
114+
</configuration>
115+
</plugin>
116+
93117
<plugin>
94-
<groupId>org.springframework.boot</groupId>
95-
<artifactId>spring-boot-maven-plugin</artifactId>
96-
<version>2.4.6</version>
118+
<artifactId>maven-assembly-plugin</artifactId>
97119
<configuration>
98-
<includeSystemScope>true</includeSystemScope>
120+
<appendAssemblyId>false</appendAssemblyId>
121+
<descriptorRefs>
122+
<descriptorRef>jar-with-dependencies</descriptorRef>
123+
</descriptorRefs>
124+
<archive>
125+
<manifest>
126+
<!-- 此处指定main方法入口的class -->
127+
<!-- <mainClass>com.xxx.Main</mainClass>-->
128+
</manifest>
129+
</archive>
99130
</configuration>
131+
<executions>
132+
<execution>
133+
<id>make-assembly</id>
134+
<phase>package</phase>
135+
<goals>
136+
<goal>single</goal>
137+
</goals>
138+
</execution>
139+
</executions>
100140
</plugin>
101141
</plugins>
102142
</build>

src/main/java/org/springframework/lock/annotation/EnableSpringLocks.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import org.springframework.context.annotation.Import;
55
import org.springframework.lock.aspect.ReadLockAspect;
66
import org.springframework.lock.aspect.SynchronizedAspect;
7+
import org.springframework.lock.aspect.WriteLockAspect;
78

89
import java.lang.annotation.ElementType;
910
import java.lang.annotation.Retention;
@@ -12,7 +13,8 @@
1213

1314
@Import({
1415
SynchronizedAspect.class,
15-
ReadLockAspect.class
16+
ReadLockAspect.class,
17+
WriteLockAspect.class
1618
})
1719
@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)
1820
@Retention(RetentionPolicy.RUNTIME)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package org.springframework.lock.aspect;
2+
3+
import org.apache.commons.logging.Log;
4+
import org.apache.commons.logging.LogFactory;
5+
import org.aspectj.lang.ProceedingJoinPoint;
6+
import org.aspectj.lang.annotation.Around;
7+
import org.aspectj.lang.annotation.Aspect;
8+
9+
import java.lang.reflect.Field;
10+
import java.util.concurrent.locks.Lock;
11+
12+
@Aspect
13+
public class WriteLockAspect {
14+
15+
private static final Log LOGGER = LogFactory.getLog(WriteLockAspect.class);
16+
17+
@Around("@annotation(org.springframework.lock.annotation.WriteLock)")
18+
public Object aroundWriteLock(ProceedingJoinPoint jp) throws Throwable {
19+
Object obj = jp.getTarget();
20+
Class<?> clz = obj.getClass();
21+
Lock writeLock = null;
22+
for (Field field : clz.getDeclaredFields()) {
23+
if ("$writeLock".equals(field.getName())){
24+
field.setAccessible(true);
25+
Object unknownLock = field.get(obj);
26+
writeLock = (Lock) unknownLock;
27+
}
28+
}
29+
Object result = null;
30+
if (writeLock != null) {
31+
writeLock.lock();
32+
try {
33+
LOGGER.info(clz.getSimpleName() + "获得写锁");
34+
result = jp.proceed();
35+
LOGGER.info(clz.getSimpleName() + "释放写锁");
36+
} finally {
37+
writeLock.unlock();
38+
}
39+
}else {
40+
LOGGER.warn(clz.getSimpleName() + "生成读锁失败,未能加锁");
41+
result = jp.proceed();
42+
}
43+
return result;
44+
}
45+
46+
}

src/main/java/org/springframework/lock/processor/ReadLockProcessor.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ public synchronized void init(ProcessingEnvironment processingEnv) {
4949
@Override
5050
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
5151
for (TypeElement annotation : annotations) {
52-
Name qualifiedName = annotation.getQualifiedName();
5352
Set<TypeElement> cls = new HashSet<TypeElement>();
5453
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(annotation);
5554
// 找到都有哪些类里面的方法用到了这个注解
@@ -70,12 +69,12 @@ public void visitClassDef(JCTree.JCClassDecl jcClassDecl) {
7069
for (JCTree jcTree : jcClassDecl.defs) {
7170
if (jcTree.getKind().equals(Tree.Kind.VARIABLE)) {
7271
JCTree.JCVariableDecl var = (JCTree.JCVariableDecl) jcTree;
73-
if ("java.util.concurrent.locks.ReadWriteLock".equalsIgnoreCase(var.vartype.type.toString()) && "$lock".equals(var.name.toString())) {
72+
if ("$lock".equals("" + var.name)) {
7473
// 找到了类中的读写锁,不修改语法树
7574
messager.printMessage(Diagnostic.Kind.NOTE, "已发现" + clz.getQualifiedName() + "类中的读写锁" + var.name);
7675
foundReadWriteLock = true;
7776
}
78-
if ("$readLock".equals(var.name.toString())){
77+
if ("$readLock".equals("" + var.name)){
7978
// 找到了类中的读锁,不修改语法树
8079
messager.printMessage(Diagnostic.Kind.NOTE, "已发现" + clz.getQualifiedName() + "类中的读锁" + var.name);
8180
foundReadLock = true;
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
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.processing.JavacProcessingEnvironment;
8+
import com.sun.tools.javac.tree.JCTree;
9+
import com.sun.tools.javac.tree.TreeMaker;
10+
import com.sun.tools.javac.tree.TreeTranslator;
11+
import com.sun.tools.javac.util.Context;
12+
import com.sun.tools.javac.util.Names;
13+
14+
import javax.annotation.processing.*;
15+
import javax.lang.model.SourceVersion;
16+
import javax.lang.model.element.Element;
17+
import javax.lang.model.element.ExecutableElement;
18+
import javax.lang.model.element.Name;
19+
import javax.lang.model.element.TypeElement;
20+
import javax.tools.Diagnostic;
21+
import java.util.HashSet;
22+
import java.util.Set;
23+
24+
import static com.sun.tools.javac.util.List.nil;
25+
26+
@SupportedAnnotationTypes("org.springframework.lock.annotation.WriteLock")
27+
@SupportedSourceVersion(SourceVersion.RELEASE_8)
28+
@AutoService(Processor.class)
29+
public class WriteLockProcessor extends AbstractProcessor {
30+
31+
private Messager messager; // 编译时期输入日志的
32+
private JavacTrees javacTrees; // 提供了待处理的抽象语法树
33+
private TreeMaker treeMaker; // 封装了创建AST节点的一些方法
34+
private Names names; // 提供了创建标识符的方法
35+
36+
@Override
37+
public synchronized void init(ProcessingEnvironment processingEnv) {
38+
super.init(processingEnv);
39+
this.messager = processingEnv.getMessager();
40+
this.javacTrees = JavacTrees.instance(processingEnv);
41+
Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
42+
this.treeMaker = TreeMaker.instance(context);
43+
this.names = Names.instance(context);
44+
}
45+
46+
@Override
47+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
48+
for (TypeElement annotation : annotations) {
49+
Set<TypeElement> cls = new HashSet<TypeElement>();
50+
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(annotation);
51+
// 找到都有哪些类里面的方法用到了这个注解
52+
for (Element element : elements) {
53+
ExecutableElement method = (ExecutableElement) element;
54+
TypeElement clz = (TypeElement) method.getEnclosingElement();
55+
messager.printMessage(Diagnostic.Kind.NOTE, "发现需要包含注解" + annotation.getQualifiedName() + "的类" + clz.getQualifiedName());
56+
cls.add(clz);
57+
}
58+
for (TypeElement clz : cls) {
59+
JCTree tree = javacTrees.getTree(clz);
60+
tree.accept(new TreeTranslator() {
61+
@Override
62+
public void visitClassDef(JCTree.JCClassDecl jcClassDecl) {
63+
// 在抽象树中找出所有的变量
64+
boolean foundReadWriteLock = false;
65+
boolean foundWriteLock = false;
66+
for (JCTree jcTree : jcClassDecl.defs) {
67+
if (jcTree.getKind().equals(Tree.Kind.VARIABLE)) {
68+
JCTree.JCVariableDecl var = (JCTree.JCVariableDecl) jcTree;
69+
if ("$lock".equals("" + var.name)) {
70+
// 找到了类中的读写锁,不修改语法树
71+
messager.printMessage(Diagnostic.Kind.NOTE, "已发现" + clz.getQualifiedName() + "类中的读写锁" + var.name);
72+
foundReadWriteLock = true;
73+
}
74+
if ("$writeLock".equals("" + var.name)){
75+
// 找到了类中的写锁,不修改语法树
76+
messager.printMessage(Diagnostic.Kind.NOTE, "已发现" + clz.getQualifiedName() + "类中的写锁" + var.name);
77+
foundWriteLock = true;
78+
}
79+
if (foundReadWriteLock && foundWriteLock)
80+
break;
81+
}
82+
}
83+
// 修改语法树
84+
JCTree.JCVariableDecl lock = makeReadWriteLock();
85+
JCTree.JCVariableDecl writeLock = makeWriteLock();
86+
if (!foundReadWriteLock) {
87+
messager.printMessage(Diagnostic.Kind.NOTE, "将为类" + clz.getQualifiedName() + "动态生成读写锁");
88+
jcClassDecl.defs = jcClassDecl.defs.append(lock);
89+
}
90+
if (!foundWriteLock) {
91+
messager.printMessage(Diagnostic.Kind.NOTE, "将为类" + clz.getQualifiedName() + "动态生成写锁");
92+
jcClassDecl.defs = jcClassDecl.defs.append(writeLock);
93+
}
94+
super.visitClassDef(jcClassDecl);
95+
}
96+
});
97+
}
98+
break;
99+
}
100+
return Boolean.TRUE;
101+
}
102+
103+
private JCTree.JCVariableDecl makeReadWriteLock(){
104+
JCTree.JCModifiers modifiers = this.treeMaker.Modifiers(Flags.PRIVATE + Flags.FINAL);
105+
JCTree.JCVariableDecl var = this.treeMaker.VarDef(
106+
modifiers,
107+
this.names.fromString("$lock"),
108+
this.memberAccess("java.util.concurrent.locks.ReentrantReadWriteLock"),
109+
this.treeMaker.NewClass(null, nil(), treeMaker.Ident(names.fromString("ReentrantReadWriteLock")), nil(), null)
110+
);
111+
return var;
112+
}
113+
114+
private JCTree.JCVariableDecl makeWriteLock(){
115+
JCTree.JCModifiers modifiers = this.treeMaker.Modifiers(Flags.PRIVATE + Flags.FINAL);
116+
JCTree.JCVariableDecl var = this.treeMaker.VarDef(
117+
modifiers,
118+
this.names.fromString("$writeLock"),
119+
this.memberAccess("java.util.concurrent.locks.Lock"),
120+
treeMaker.Apply(nil(), treeMaker.Select(treeMaker.Ident(names.fromString("$lock")), names.fromString("writeLock")), nil())
121+
);
122+
return var;
123+
}
124+
125+
private JCTree.JCExpression memberAccess(String components) {
126+
String[] componentArray = components.split("\\.");
127+
JCTree.JCExpression expr = treeMaker.Ident(this.names.fromString(componentArray[0]));
128+
for (int i = 1; i < componentArray.length; i++) {
129+
expr = treeMaker.Select(expr, this.names.fromString(componentArray[i]));
130+
}
131+
return expr;
132+
}
133+
}

src/test/java/example/name/controller/BaseController.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,11 @@ public String testReadLock(){
2727
String result = this.baseService.testReadLock();
2828
return result;
2929
}
30+
31+
@RequestMapping(value = "/testWriteLock", method = RequestMethod.GET)
32+
@ResponseBody
33+
public String testWriteLock(){
34+
String result = this.baseService.testWriteLock();
35+
return result;
36+
}
3037
}

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import org.apache.commons.logging.LogFactory;
55
import org.springframework.lock.annotation.ReadLock;
66
import org.springframework.lock.annotation.Synchronized;
7+
import org.springframework.lock.annotation.WriteLock;
78
import org.springframework.stereotype.Service;
89

910
import java.util.concurrent.locks.Lock;
@@ -14,9 +15,9 @@ public class BaseService {
1415

1516
private static final Log LOGGER = LogFactory.getLog(BaseService.class);
1617

17-
// private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
18+
// private final ReentrantReadWriteLock $lock = new ReentrantReadWriteLock();
1819
//
19-
// private final Lock readLock = lock.readLock();
20+
// private final Lock $readLock = $lock.readLock();
2021
//
2122
// private final Lock writeLock = lock.writeLock();
2223

@@ -45,4 +46,17 @@ public String testReadLock() {
4546
LOGGER.info(name + "执行结束");
4647
return "testReadLock 执行结束";
4748
}
49+
50+
@WriteLock
51+
public String testWriteLock(){
52+
String name = Thread.currentThread().getName();
53+
LOGGER.info(name + "开始执行");
54+
try {
55+
Thread.sleep(5000);
56+
} catch (InterruptedException e) {
57+
e.printStackTrace();
58+
}
59+
LOGGER.info(name + "执行结束");
60+
return "testWriteLock 执行结束";
61+
}
4862
}

0 commit comments

Comments
 (0)