Skip to content

Commit 34d225d

Browse files
committed
version 0.9.0.0 update
完善读写锁注解,现在可以使用自定义的读写锁
1 parent 458f1d9 commit 34d225d

File tree

10 files changed

+95
-72
lines changed

10 files changed

+95
-72
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,7 @@
7676
<tr>
7777
<td>0.8.1.0</td><td>完善写锁,提供最长等待时间,最长执行时间,是否强制执行等属性,全方位避免死锁</td><td>2022年2月4日</td>
7878
</tr>
79+
<tr>
80+
<td>0.9.0.0</td><td>完善读写锁注解,现在可以使用自定义的读写锁</td><td>2022年2月4日</td>
81+
</tr>
7982
</table>

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@
1515
public @interface ReadLock {
1616

1717
/**
18-
* 是否公平锁
18+
* 读写锁变量的名称,该变量必须是{@code ReentrantReadWriteLock}类的对象或其子类对象
19+
* @return 默认使用编译生成的
20+
*/
21+
String value() default "";
22+
23+
/**
24+
* 编译时生成的是否公平锁,该属性仅在{@code value}属性保持默认时才生效
1925
* @return 默认null,如果有自定义值则覆盖默认值
2026
*/
2127
BooleanEnum fair() default NULL;

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@
1515
public @interface WriteLock {
1616

1717
/**
18-
* 是否公平锁
18+
* 读写锁变量的名称,该变量必须是{@code ReentrantReadWriteLock}类的对象或其子类对象
19+
* @return 默认使用编译生成的
20+
*/
21+
String value() default "";
22+
23+
/**
24+
* 编译时生成的是否公平锁,该属性仅在{@code value}属性保持默认时才生效
1925
* @return 默认null,如果有自定义值则覆盖默认值
2026
*/
2127
BooleanEnum fair() default NULL;

src/main/java/org/springframework/lock/annotation/package-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
* 每个注解上都有对应的注释,写得很清楚,自己看就可以了,不加以赘述.
44
* 需要注意的是,如果需要使锁注解生效,需要在springboot启动类上添加{@code @EnableSpringLocks}注解
55
* @author 宗祥瑞
6-
* @version 0.8.1.0
6+
* @version 0.9.0.0
77
*/
88
package org.springframework.lock.annotation;

src/main/java/org/springframework/lock/aspect/ReadLockAspect.java

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.aspectj.lang.reflect.MethodSignature;
99
import org.springframework.lock.annotation.ReadLock;
1010
import org.springframework.lock.timer.InterruptTimer;
11+
import org.springframework.util.StringUtils;
1112

1213
import java.lang.reflect.Field;
1314
import java.lang.reflect.Method;
@@ -35,49 +36,52 @@ public class ReadLockAspect {
3536
*/
3637
@Around("@annotation(org.springframework.lock.annotation.ReadLock)")
3738
public Object aroundReadLock(ProceedingJoinPoint jp) throws Throwable {
38-
Object obj = jp.getTarget();
39-
Class<?> clz = obj.getClass();
40-
Lock readLock = null;
41-
ReentrantReadWriteLock lock = null;
42-
for (Field field : clz.getDeclaredFields()) {
43-
if ("$readLock".equals(field.getName())){
44-
field.setAccessible(true);
45-
readLock = (Lock) field.get(obj);
46-
}
47-
if ("$lock".equals(field.getName())){
48-
field.setAccessible(true);
49-
lock = (ReentrantReadWriteLock) field.get(obj);
50-
}
51-
if (lock != null && readLock != null)
52-
// 都找到了
53-
break;
54-
}
55-
if (readLock == null || lock == null){
56-
// 连锁都没拿到,说明编译期间出了问题
57-
LOGGER.warn(clz.getSimpleName() + "编译时生成读写锁锁失败,未能加锁");
58-
return jp.proceed();
59-
}
60-
39+
// 获取注解的属性
6140
long waitTime = Long.MAX_VALUE;
6241
long executeTime = Long.MAX_VALUE;
6342
boolean isContinueIfElapsed = false;
6443
boolean withLockIfContinue = false;
44+
String lockName = null;
6545

6646
MethodSignature signature = (MethodSignature) jp.getSignature();
6747
Method method = signature.getMethod();
68-
if (method == null) {
69-
// 没拿到方法,那注解给了谁呢?
70-
LOGGER.warn("没拿到方法" + signature);
71-
return jp.proceed();
72-
}
7348
ReadLock annotation = method.getAnnotation(ReadLock.class);
7449
if (annotation != null) {
7550
waitTime = annotation.waitTime();
7651
executeTime = annotation.executeTime();
7752
isContinueIfElapsed = annotation.isContinueIfElapsed();
7853
withLockIfContinue = annotation.withLockIfContinue();
54+
lockName = annotation.value();
55+
}
56+
57+
// 获取锁对象
58+
Lock readLock = null;
59+
ReentrantReadWriteLock lock = null;
60+
Object obj = jp.getTarget();
61+
Class<?> clz = obj.getClass();
62+
Field field = null;
63+
64+
if (StringUtils.hasText(lockName)){
65+
field = clz.getDeclaredField(lockName);
66+
field.setAccessible(true);
67+
lock = (ReentrantReadWriteLock) field.get(obj);
68+
readLock = lock.readLock();
69+
}else {
70+
field = clz.getDeclaredField("$readLock");
71+
field.setAccessible(true);
72+
readLock = (Lock) field.get(obj);
73+
field = clz.getDeclaredField("$lock");
74+
field.setAccessible(true);
75+
lock = (ReentrantReadWriteLock) field.get(obj);
76+
}
77+
78+
if (readLock == null || lock == null){
79+
// 连锁都没拿到,说明编译期间出了问题
80+
LOGGER.warn(clz.getSimpleName() + "获取锁错误,请检查锁名称是否正确");
81+
return jp.proceed();
7982
}
8083

84+
// 尝试加锁,不行就结束掉别人的线程
8185
Object result = null;
8286
boolean locked = readLock.tryLock(waitTime, MILLISECONDS);
8387
if (locked) {
@@ -91,12 +95,12 @@ public Object aroundReadLock(ProceedingJoinPoint jp) throws Throwable {
9195
Thread lockedThread = (Thread) getOwner.invoke(lock);
9296
lockedThread.interrupt();
9397
if (readLock.tryLock(waitTime, MILLISECONDS)){
94-
LOGGER.warn("等待时间耗尽,终止线程" + lockedThread + "以强制获得锁");
98+
LOGGER.warn("等待时间耗尽,终止线程" + lockedThread + "以强制获得读锁" + readLock);
9599
result = this.processMethod(jp, readLock, executeTime);
96100
}else{
97101
lockedThread.stop();
98102
if (readLock.tryLock(waitTime, MILLISECONDS)){
99-
LOGGER.warn("等待时间耗尽,终止线程" + lockedThread + "以强制获得锁");
103+
LOGGER.warn("等待时间耗尽,终止线程" + lockedThread + "以强制获得读锁" + readLock);
100104
result = this.processMethod(jp, readLock, executeTime);
101105
}
102106
}
@@ -105,7 +109,7 @@ public Object aroundReadLock(ProceedingJoinPoint jp) throws Throwable {
105109
result = jp.proceed();
106110
}
107111
}else {
108-
LOGGER.warn("等待时间耗尽,将不执行" + method.getName());
112+
LOGGER.warn("等待时间耗尽,放弃执行" + method.getName());
109113
}
110114
}
111115
return result;
@@ -121,13 +125,13 @@ public Object aroundReadLock(ProceedingJoinPoint jp) throws Throwable {
121125
*/
122126
private Object processMethod(ProceedingJoinPoint jp, Lock readLock, long executeTime) throws Throwable {
123127
Object result = null;
124-
LOGGER.info(Thread.currentThread().getName() + "获得读锁");
128+
LOGGER.info(Thread.currentThread().getName() + "获得读锁" + readLock);
125129
new InterruptTimer(Thread.currentThread(), executeTime);
126130
try {
127131
result = jp.proceed();
128132
} finally {
129133
readLock.unlock();
130-
LOGGER.info(Thread.currentThread().getName() + "释放读锁");
134+
LOGGER.info(Thread.currentThread().getName() + "释放读锁" + readLock);
131135
}
132136
return result;
133137
}

src/main/java/org/springframework/lock/aspect/WriteLockAspect.java

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.aspectj.lang.reflect.MethodSignature;
99
import org.springframework.lock.annotation.WriteLock;
1010
import org.springframework.lock.timer.InterruptTimer;
11+
import org.springframework.util.StringUtils;
1112

1213
import java.lang.reflect.Field;
1314
import java.lang.reflect.Method;
@@ -35,49 +36,52 @@ public class WriteLockAspect {
3536
*/
3637
@Around("@annotation(org.springframework.lock.annotation.WriteLock)")
3738
public Object aroundWriteLock(ProceedingJoinPoint jp) throws Throwable {
38-
Object obj = jp.getTarget();
39-
Class<?> clz = obj.getClass();
40-
Lock writeLock = null;
41-
ReentrantReadWriteLock lock = null;
42-
for (Field field : clz.getDeclaredFields()) {
43-
if ("$writeLock".equals(field.getName())){
44-
field.setAccessible(true);
45-
writeLock = (Lock) field.get(obj);
46-
}
47-
if ("$lock".equals(field.getName())){
48-
field.setAccessible(true);
49-
lock = (ReentrantReadWriteLock) field.get(obj);
50-
}
51-
if (lock != null && writeLock != null)
52-
// 都找到了
53-
break;
54-
}
55-
if (lock == null || writeLock == null){
56-
// 连锁都没拿到,说明编译期间出了问题
57-
LOGGER.warn(clz.getSimpleName() + "编译时生成读写锁锁失败,未能加锁");
58-
return jp.proceed();
59-
}
60-
39+
// 获取注解的属性
6140
long waitTime = Long.MAX_VALUE;
6241
long executeTime = Long.MAX_VALUE;
6342
boolean isContinueIfElapsed = false;
6443
boolean withLockIfContinue = false;
44+
String lockName = null;
6545

6646
MethodSignature signature = (MethodSignature) jp.getSignature();
6747
Method method = signature.getMethod();
68-
if (method == null) {
69-
// 没拿到方法,那注解给了谁呢?
70-
LOGGER.warn("没拿到方法" + signature);
71-
return jp.proceed();
72-
}
7348
WriteLock annotation = method.getAnnotation(WriteLock.class);
7449
if (annotation != null) {
7550
waitTime = annotation.waitTime();
7651
executeTime = annotation.executeTime();
7752
isContinueIfElapsed = annotation.isContinueIfElapsed();
7853
withLockIfContinue = annotation.withLockIfContinue();
54+
lockName = annotation.value();
55+
}
56+
57+
// 获取锁对象
58+
Lock writeLock = null;
59+
ReentrantReadWriteLock lock = null;
60+
Object obj = jp.getTarget();
61+
Class<?> clz = obj.getClass();
62+
Field field = null;
63+
64+
if (StringUtils.hasText(lockName)){
65+
field = clz.getDeclaredField(lockName);
66+
field.setAccessible(true);
67+
lock = (ReentrantReadWriteLock) field.get(obj);
68+
writeLock = lock.writeLock();
69+
}else {
70+
field = clz.getDeclaredField("$writeLock");
71+
field.setAccessible(true);
72+
writeLock = (Lock) field.get(obj);
73+
field = clz.getDeclaredField("$lock");
74+
field.setAccessible(true);
75+
lock = (ReentrantReadWriteLock) field.get(obj);
76+
}
77+
78+
if (lock == null || writeLock == null){
79+
// 连锁都没拿到,说明编译期间出了问题
80+
LOGGER.warn(clz.getSimpleName() + "编译时生成读写锁锁失败,未能加锁");
81+
return jp.proceed();
7982
}
8083

84+
// 尝试加锁,不行就结束掉别人的线程
8185
Object result = null;
8286
boolean locked = writeLock.tryLock(waitTime, MILLISECONDS);
8387
if (locked) {
@@ -91,12 +95,12 @@ public Object aroundWriteLock(ProceedingJoinPoint jp) throws Throwable {
9195
Thread lockedThread = (Thread) getOwner.invoke(lock);
9296
lockedThread.interrupt();
9397
if (writeLock.tryLock(waitTime, MILLISECONDS)){
94-
LOGGER.warn("等待时间耗尽,中断线程" + lockedThread + "以强制获得锁");
98+
LOGGER.warn("等待时间耗尽,中断线程" + lockedThread + "以强制获得写锁" + writeLock);
9599
result = this.processMethod(jp, writeLock, executeTime);
96100
}else {
97101
lockedThread.stop();
98102
if (writeLock.tryLock(waitTime, MILLISECONDS)) {
99-
LOGGER.warn("等待时间耗尽,终止线程" + lockedThread + "以强制获得锁");
103+
LOGGER.warn("等待时间耗尽,终止线程" + lockedThread + "以强制获得写锁" + writeLock);
100104
result = this.processMethod(jp, writeLock, executeTime);
101105
}
102106
}
@@ -122,13 +126,13 @@ public Object aroundWriteLock(ProceedingJoinPoint jp) throws Throwable {
122126
*/
123127
private Object processMethod(ProceedingJoinPoint jp, Lock writeLock, long executeTime) throws Throwable {
124128
Object result = null;
125-
LOGGER.info(Thread.currentThread().getName() + "获得写锁");
129+
LOGGER.info(Thread.currentThread().getName() + "获得写锁" + writeLock);
126130
new InterruptTimer(Thread.currentThread(), executeTime);
127131
try {
128132
result = jp.proceed();
129133
} finally {
130134
writeLock.unlock();
131-
LOGGER.info(Thread.currentThread().getName() + "释放写锁");
135+
LOGGER.info(Thread.currentThread().getName() + "释放写锁" + writeLock);
132136
}
133137
return result;
134138
}

src/main/java/org/springframework/lock/aspect/package-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
* 每个切面都有注释,没什么好说的,不加以赘述.
44
* 切面这部分需要托管到spring容器中去执行.
55
* @author 宗祥瑞
6-
* @version 0.8.1.0
6+
* @version 0.9.0.0
77
*/
88
package org.springframework.lock.aspect;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* 这是关于枚举类型的包.
33
* 写得很清楚,直接看代码就好了.
4-
* @version 0.8.1.0
4+
* @version 0.9.0.0
55
* @author 宗祥瑞
66
*/
77
package org.springframework.lock.enumeration;

src/main/java/org/springframework/lock/processor/package-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
* 它的原理与lombok有些许类似,但代码风格比lombok更好理解,一看就懂
55
* 每个处理器都写了注释,写得都很清楚,不加以赘述
66
* @author 宗祥瑞
7-
* @version 0.8.1.0
7+
* @version 0.9.0.0
88
*/
99
package org.springframework.lock.processor;

src/main/java/org/springframework/lock/timer/package-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
* 意思就是在多长时间后执行什么功能,或者要求每过多长时间执行什么功能.
44
* java不能多继承,所以用内部类来实现
55
* @author 宗祥瑞
6-
* @version 0.8.1.0
6+
* @version 0.9.0.0
77
*/
88
package org.springframework.lock.timer;

0 commit comments

Comments
 (0)