lock
This commit is contained in:
@@ -27,6 +27,7 @@ module org.redkale {
|
|||||||
exports org.redkale.convert.proto;
|
exports org.redkale.convert.proto;
|
||||||
exports org.redkale.inject;
|
exports org.redkale.inject;
|
||||||
exports org.redkale.lock;
|
exports org.redkale.lock;
|
||||||
|
exports org.redkale.lock.spi;
|
||||||
exports org.redkale.mq;
|
exports org.redkale.mq;
|
||||||
exports org.redkale.net;
|
exports org.redkale.net;
|
||||||
exports org.redkale.net.client;
|
exports org.redkale.net.client;
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.asm;
|
package org.redkale.asm;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import org.redkale.convert.json.JsonConvert;
|
import org.redkale.convert.json.JsonConvert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,6 +40,10 @@ public class AsmMethodBean {
|
|||||||
this.fieldNames = new ArrayList<>();
|
this.fieldNames = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static AsmMethodBean get(Map<String, AsmMethodBean> map, Method method) {
|
||||||
|
return map == null ? null : map.get(method.getName() + ":" + Type.getMethodDescriptor(method));
|
||||||
|
}
|
||||||
|
|
||||||
void removeEmptyNames() {
|
void removeEmptyNames() {
|
||||||
if (fieldNames != null) {
|
if (fieldNames != null) {
|
||||||
while (fieldNames.remove(" "));
|
while (fieldNames.remove(" "));
|
||||||
|
|||||||
@@ -30,15 +30,16 @@ public interface AsmMethodBoost<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回的List中参数列表可能会比方法参数量多,因为方法内的临时变量也会存入list中, 所以需要list的元素集合比方法的参数多
|
|
||||||
*
|
*
|
||||||
* @param map
|
* 返回一个类所有方法的字节信息, key为: method.getName+':'+Type.getMethodDescriptor(method)
|
||||||
* @param clazz
|
|
||||||
*
|
*
|
||||||
* @return
|
* @param clazz Class
|
||||||
|
*
|
||||||
|
* @return Map
|
||||||
*/
|
*/
|
||||||
public static Map<String, AsmMethodBean> getMethodBean(Class clazz) {
|
public static Map<String, AsmMethodBean> getMethodBeans(Class clazz) {
|
||||||
Map<String, AsmMethodBean> rs = MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), clazz);
|
Map<String, AsmMethodBean> rs = MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), clazz);
|
||||||
|
//返回的List中参数列表可能会比方法参数量多,因为方法内的临时变量也会存入list中, 所以需要list的元素集合比方法的参数多
|
||||||
rs.values().forEach(AsmMethodBean::removeEmptyNames);
|
rs.values().forEach(AsmMethodBean::removeEmptyNames);
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import org.redkale.convert.proto.ProtobufFactory;
|
|||||||
import org.redkale.inject.ResourceEvent;
|
import org.redkale.inject.ResourceEvent;
|
||||||
import org.redkale.inject.ResourceFactory;
|
import org.redkale.inject.ResourceFactory;
|
||||||
import org.redkale.inject.ResourceTypeLoader;
|
import org.redkale.inject.ResourceTypeLoader;
|
||||||
|
import org.redkale.lock.spi.LockModuleEngine;
|
||||||
import org.redkale.mq.*;
|
import org.redkale.mq.*;
|
||||||
import org.redkale.net.*;
|
import org.redkale.net.*;
|
||||||
import org.redkale.net.http.*;
|
import org.redkale.net.http.*;
|
||||||
@@ -315,8 +316,9 @@ public final class Application {
|
|||||||
moduleEngines.add(this.sourceModule); //放第一,很多module依赖于source
|
moduleEngines.add(this.sourceModule); //放第一,很多module依赖于source
|
||||||
moduleEngines.add(new MessageModuleEngine(this));
|
moduleEngines.add(new MessageModuleEngine(this));
|
||||||
moduleEngines.add(new ClusterModuleEngine(this));
|
moduleEngines.add(new ClusterModuleEngine(this));
|
||||||
moduleEngines.add(new CacheModuleEngine(this));
|
|
||||||
moduleEngines.add(new ScheduleModuleEngine(this));
|
moduleEngines.add(new ScheduleModuleEngine(this));
|
||||||
|
moduleEngines.add(new CacheModuleEngine(this));
|
||||||
|
moduleEngines.add(new LockModuleEngine(this));
|
||||||
|
|
||||||
//根据本地日志配置文件初始化日志
|
//根据本地日志配置文件初始化日志
|
||||||
loggingModule.reconfigLogging(true, appConfig.locaLogProperties);
|
loggingModule.reconfigLogging(true, appConfig.locaLogProperties);
|
||||||
|
|||||||
@@ -71,11 +71,10 @@ public class CacheAsmMethodBoost implements AsmMethodBoost {
|
|||||||
|
|
||||||
final String rsMethodName = method.getName() + "_cache";
|
final String rsMethodName = method.getName() + "_cache";
|
||||||
{
|
{
|
||||||
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBean(serviceType);
|
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(serviceType);
|
||||||
String desc = Type.getMethodDescriptor(method);
|
AsmMethodBean methodBean = AsmMethodBean.get(methodBeans, method);
|
||||||
AsmMethodBean methodBean = methodBeans.get(method.getName() + ":" + desc);
|
|
||||||
|
|
||||||
final String cacheDynDesc = Type.getDescriptor(CacheDyn.class);
|
final String cacheDynDesc = Type.getDescriptor(DynForCache.class);
|
||||||
MethodDebugVisitor mv;
|
MethodDebugVisitor mv;
|
||||||
AnnotationVisitor av;
|
AnnotationVisitor av;
|
||||||
String signature = null;
|
String signature = null;
|
||||||
|
|||||||
@@ -18,5 +18,5 @@ import java.lang.annotation.Target;
|
|||||||
@Documented
|
@Documented
|
||||||
@Target({METHOD})
|
@Target({METHOD})
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
public @interface CacheDyn {
|
public @interface DynForCache {
|
||||||
}
|
}
|
||||||
18
src/main/java/org/redkale/lock/LockManager.java
Normal file
18
src/main/java/org/redkale/lock/LockManager.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.redkale.lock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 锁管理器
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*
|
||||||
|
* @since 2.8.0
|
||||||
|
*/
|
||||||
|
public interface LockManager {
|
||||||
|
|
||||||
|
}
|
||||||
23
src/main/java/org/redkale/lock/spi/DynForLock.java
Normal file
23
src/main/java/org/redkale/lock/spi/DynForLock.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.redkale.lock.spi;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
@Inherited
|
||||||
|
@Documented
|
||||||
|
@Target({METHOD})
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
public @interface DynForLock {
|
||||||
|
|
||||||
|
}
|
||||||
169
src/main/java/org/redkale/lock/spi/LockAsmMethodBoost.java
Normal file
169
src/main/java/org/redkale/lock/spi/LockAsmMethodBoost.java
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.redkale.lock.spi;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.redkale.asm.AnnotationVisitor;
|
||||||
|
import org.redkale.asm.AsmMethodBean;
|
||||||
|
import org.redkale.asm.AsmMethodBoost;
|
||||||
|
import org.redkale.asm.Asms;
|
||||||
|
import org.redkale.asm.ClassWriter;
|
||||||
|
import org.redkale.asm.Label;
|
||||||
|
import org.redkale.asm.MethodDebugVisitor;
|
||||||
|
import static org.redkale.asm.Opcodes.*;
|
||||||
|
import org.redkale.asm.Type;
|
||||||
|
import org.redkale.lock.Locked;
|
||||||
|
import org.redkale.util.RedkaleException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
public class LockAsmMethodBoost implements AsmMethodBoost {
|
||||||
|
|
||||||
|
protected final Class serviceType;
|
||||||
|
|
||||||
|
public LockAsmMethodBoost(Class serviceType) {
|
||||||
|
this.serviceType = serviceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String doMethod(ClassWriter cw, String newDynName, String fieldPrefix, Method method, final String newMethodName) {
|
||||||
|
Locked cached = method.getAnnotation(Locked.class);
|
||||||
|
if (cached == null) {
|
||||||
|
return newMethodName;
|
||||||
|
}
|
||||||
|
if (Modifier.isFinal(method.getModifiers()) || Modifier.isStatic(method.getModifiers())) {
|
||||||
|
throw new RedkaleException("@" + Locked.class.getSimpleName() + " can not on final or static method, but on " + method);
|
||||||
|
}
|
||||||
|
if (!Modifier.isProtected(method.getModifiers()) && !Modifier.isPublic(method.getModifiers())) {
|
||||||
|
throw new RedkaleException("@" + Locked.class.getSimpleName() + " must on protected or public method, but on " + method);
|
||||||
|
}
|
||||||
|
int acc;
|
||||||
|
String nowMethodName;
|
||||||
|
if (newMethodName == null) {
|
||||||
|
nowMethodName = method.getName();
|
||||||
|
acc = Modifier.isProtected(method.getModifiers()) ? ACC_PROTECTED : ACC_PUBLIC;
|
||||||
|
} else {
|
||||||
|
acc = ACC_PRIVATE;
|
||||||
|
nowMethodName = newMethodName;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String rsMethodName = method.getName() + "_lock";
|
||||||
|
{
|
||||||
|
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(serviceType);
|
||||||
|
AsmMethodBean methodBean = AsmMethodBean.get(methodBeans, method);
|
||||||
|
|
||||||
|
final String cacheDynDesc = Type.getDescriptor(DynForLock.class);
|
||||||
|
MethodDebugVisitor mv;
|
||||||
|
AnnotationVisitor av;
|
||||||
|
String signature = null;
|
||||||
|
String[] exceptions = null;
|
||||||
|
if (methodBean == null) {
|
||||||
|
Class<?>[] expTypes = method.getExceptionTypes();
|
||||||
|
if (expTypes.length > 0) {
|
||||||
|
exceptions = new String[expTypes.length];
|
||||||
|
for (int i = 0; i < expTypes.length; i++) {
|
||||||
|
exceptions[i] = expTypes[i].getName().replace('.', '/');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
signature = methodBean.getSignature();
|
||||||
|
exceptions = methodBean.getExceptions();
|
||||||
|
}
|
||||||
|
//需要定义一个新方法调用 this.rsMethodName
|
||||||
|
mv = new MethodDebugVisitor(cw.visitMethod(acc, nowMethodName, Type.getMethodDescriptor(method), signature, exceptions));
|
||||||
|
//mv.setDebug(true);
|
||||||
|
Label l0 = new Label();
|
||||||
|
mv.visitLabel(l0);
|
||||||
|
{
|
||||||
|
av = mv.visitAnnotation(cacheDynDesc, true);
|
||||||
|
av.visitEnd();
|
||||||
|
final Annotation[] anns = method.getAnnotations();
|
||||||
|
for (Annotation ann : anns) {
|
||||||
|
if (ann.annotationType() != Locked.class) {
|
||||||
|
Asms.visitAnnotation(mv.visitAnnotation(Type.getDescriptor(ann.annotationType()), true), ann);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ //给参数加上原有的Annotation
|
||||||
|
final Annotation[][] anns = method.getParameterAnnotations();
|
||||||
|
for (int k = 0; k < anns.length; k++) {
|
||||||
|
for (Annotation ann : anns[k]) {
|
||||||
|
Asms.visitAnnotation(mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
|
//传参数
|
||||||
|
Class[] paramTypes = method.getParameterTypes();
|
||||||
|
List<Integer> insns = new ArrayList<>();
|
||||||
|
int insn = 0;
|
||||||
|
for (Class pt : paramTypes) {
|
||||||
|
insn++;
|
||||||
|
if (pt.isPrimitive()) {
|
||||||
|
if (pt == long.class) {
|
||||||
|
mv.visitVarInsn(LLOAD, insn++);
|
||||||
|
} else if (pt == float.class) {
|
||||||
|
mv.visitVarInsn(FLOAD, insn++);
|
||||||
|
} else if (pt == double.class) {
|
||||||
|
mv.visitVarInsn(DLOAD, insn++);
|
||||||
|
} else {
|
||||||
|
mv.visitVarInsn(ILOAD, insn);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mv.visitVarInsn(ALOAD, insn);
|
||||||
|
}
|
||||||
|
insns.add(insn);
|
||||||
|
}
|
||||||
|
mv.visitMethodInsn(INVOKESPECIAL, newDynName, rsMethodName, Type.getMethodDescriptor(method), false);
|
||||||
|
if (method.getGenericReturnType() == void.class) {
|
||||||
|
mv.visitInsn(RETURN);
|
||||||
|
} else {
|
||||||
|
Class returnclz = method.getReturnType();
|
||||||
|
if (returnclz.isPrimitive()) {
|
||||||
|
if (returnclz == long.class) {
|
||||||
|
mv.visitInsn(LRETURN);
|
||||||
|
} else if (returnclz == float.class) {
|
||||||
|
mv.visitInsn(FRETURN);
|
||||||
|
} else if (returnclz == double.class) {
|
||||||
|
mv.visitInsn(DRETURN);
|
||||||
|
} else {
|
||||||
|
mv.visitInsn(IRETURN);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mv.visitInsn(ARETURN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (methodBean != null && paramTypes.length > 0) {
|
||||||
|
Label l2 = new Label();
|
||||||
|
mv.visitLabel(l2);
|
||||||
|
//mv.visitLocalVariable("this", thisClassDesc, null, l0, l2, 0);
|
||||||
|
List<String> fieldNames = methodBean.getFieldNames();
|
||||||
|
for (int i = 0; i < paramTypes.length; i++) {
|
||||||
|
mv.visitLocalVariable(fieldNames.get(i), Type.getDescriptor(paramTypes[i]), null, l0, l2, insns.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mv.visitMaxs(20, 20);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
return rsMethodName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doAfterMethods(ClassWriter cw, String newDynName, String fieldPrefix) {
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doInstance(Object service) {
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
22
src/main/java/org/redkale/lock/spi/LockManagerProvider.java
Normal file
22
src/main/java/org/redkale/lock/spi/LockManagerProvider.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.redkale.lock.spi;
|
||||||
|
|
||||||
|
import org.redkale.lock.LockManager;
|
||||||
|
import org.redkale.util.InstanceProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 自定义的LockManager加载器, 如果标记@Priority加载器的优先级需要大于1000, 1000以下预留给官方加载器
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
* @since 2.8.0
|
||||||
|
*/
|
||||||
|
public interface LockManagerProvider extends InstanceProvider<LockManager> {
|
||||||
|
|
||||||
|
}
|
||||||
58
src/main/java/org/redkale/lock/spi/LockManagerService.java
Normal file
58
src/main/java/org/redkale/lock/spi/LockManagerService.java
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.redkale.lock.spi;
|
||||||
|
|
||||||
|
import org.redkale.annotation.AutoLoad;
|
||||||
|
import org.redkale.annotation.Component;
|
||||||
|
import org.redkale.annotation.Nullable;
|
||||||
|
import org.redkale.annotation.Resource;
|
||||||
|
import org.redkale.annotation.ResourceType;
|
||||||
|
import org.redkale.boot.Application;
|
||||||
|
import org.redkale.lock.LockManager;
|
||||||
|
import org.redkale.service.Local;
|
||||||
|
import org.redkale.service.Service;
|
||||||
|
import org.redkale.source.CacheSource;
|
||||||
|
import org.redkale.util.AnyValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
@Local
|
||||||
|
@Component
|
||||||
|
@AutoLoad(false)
|
||||||
|
@ResourceType(LockManager.class)
|
||||||
|
public class LockManagerService implements LockManager, Service {
|
||||||
|
|
||||||
|
//是否开启锁
|
||||||
|
protected boolean enabled = true;
|
||||||
|
|
||||||
|
//配置
|
||||||
|
protected AnyValue config;
|
||||||
|
|
||||||
|
@Resource(required = false)
|
||||||
|
protected Application application;
|
||||||
|
|
||||||
|
//远程缓存Source
|
||||||
|
protected CacheSource remoteSource;
|
||||||
|
|
||||||
|
protected LockManagerService(@Nullable CacheSource remoteSource) {
|
||||||
|
this.remoteSource = remoteSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
//一般用于独立组件
|
||||||
|
public static LockManagerService create(@Nullable CacheSource remoteSource) {
|
||||||
|
return new LockManagerService(remoteSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean enabled() {
|
||||||
|
return this.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LockManagerService enabled(boolean val) {
|
||||||
|
this.enabled = val;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
106
src/main/java/org/redkale/lock/spi/LockModuleEngine.java
Normal file
106
src/main/java/org/redkale/lock/spi/LockModuleEngine.java
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.redkale.lock.spi;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
import org.redkale.asm.AsmMethodBoost;
|
||||||
|
import org.redkale.boot.Application;
|
||||||
|
import org.redkale.boot.ModuleEngine;
|
||||||
|
import org.redkale.lock.LockManager;
|
||||||
|
import org.redkale.service.Service;
|
||||||
|
import org.redkale.util.AnyValue;
|
||||||
|
import org.redkale.util.InstanceProvider;
|
||||||
|
import org.redkale.util.RedkaleClassLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
public class LockModuleEngine extends ModuleEngine {
|
||||||
|
|
||||||
|
//全局锁管理器
|
||||||
|
private LockManager lockManager;
|
||||||
|
|
||||||
|
private AnyValue config;
|
||||||
|
|
||||||
|
public LockModuleEngine(Application application) {
|
||||||
|
super(application);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断模块的配置项合并策略, 返回null表示模块不识别此配置项
|
||||||
|
*
|
||||||
|
* @param path 配置项路径
|
||||||
|
* @param key 配置项名称
|
||||||
|
* @param val1 配置项原值
|
||||||
|
* @param val2 配置项新值
|
||||||
|
*
|
||||||
|
* @return MergeEnum
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AnyValue.MergeEnum mergeAppConfigStrategy(String path, String key, AnyValue val1, AnyValue val2) {
|
||||||
|
if ("".equals(path) && "lock".equals(key)) {
|
||||||
|
return AnyValue.MergeEnum.REPLACE;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态扩展类的方法
|
||||||
|
*
|
||||||
|
* @param serviceClass 类
|
||||||
|
*
|
||||||
|
* @return 方法动态扩展器
|
||||||
|
*/
|
||||||
|
public AsmMethodBoost createAsmMethodBoost(Class serviceClass) {
|
||||||
|
return new LockAsmMethodBoost(serviceClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束Application.init方法前被调用
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onAppPostInit() {
|
||||||
|
//设置锁管理器
|
||||||
|
this.config = application.getAppConfig().getAnyValue("lock");
|
||||||
|
this.lockManager = createManager(this.config);
|
||||||
|
if (!application.isCompileMode()) {
|
||||||
|
this.resourceFactory.inject(this.lockManager);
|
||||||
|
if (this.lockManager instanceof Service) {
|
||||||
|
((Service) this.lockManager).init(this.config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.resourceFactory.register("", LockManager.class, this.lockManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 进入Application.shutdown方法被调用
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onAppPreShutdown() {
|
||||||
|
if (!application.isCompileMode() && this.lockManager instanceof Service) {
|
||||||
|
((Service) this.lockManager).destroy(this.config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private LockManager createManager(AnyValue conf) {
|
||||||
|
Iterator<LockManagerProvider> it = ServiceLoader.load(LockManagerProvider.class, application.getClassLoader()).iterator();
|
||||||
|
RedkaleClassLoader.putServiceLoader(LockManagerProvider.class);
|
||||||
|
List<LockManagerProvider> providers = new ArrayList<>();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
LockManagerProvider provider = it.next();
|
||||||
|
if (provider != null && provider.acceptsConf(conf)) {
|
||||||
|
RedkaleClassLoader.putReflectionPublicConstructors(provider.getClass(), provider.getClass().getName());
|
||||||
|
providers.add(provider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (LockManagerProvider provider : InstanceProvider.sort(providers)) {
|
||||||
|
return provider.createInstance();
|
||||||
|
}
|
||||||
|
return LockManagerService.create(null).enabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -113,64 +113,6 @@ public final class Rest {
|
|||||||
private Rest() {
|
private Rest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static class MethodParamClassVisitor extends ClassVisitor {
|
|
||||||
|
|
||||||
private final Map<String, List<String>> fieldMap;
|
|
||||||
|
|
||||||
public MethodParamClassVisitor(int api, final Map<String, List<String>> fieldmap) {
|
|
||||||
super(api);
|
|
||||||
this.fieldMap = fieldmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
|
||||||
if (java.lang.reflect.Modifier.isStatic(access)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
List<String> fieldnames = new ArrayList<>();
|
|
||||||
String key = name + ":" + desc;
|
|
||||||
if (fieldMap.containsKey(key)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
fieldMap.put(key, fieldnames);
|
|
||||||
return new MethodVisitor(Opcodes.ASM6) {
|
|
||||||
@Override
|
|
||||||
public void visitLocalVariable(String name, String description, String signature, Label start, Label end, int index) {
|
|
||||||
if (index < 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int size = fieldnames.size();
|
|
||||||
//index并不会按顺序执行的
|
|
||||||
if (index > size) {
|
|
||||||
for (int i = size; i < index; i++) {
|
|
||||||
fieldnames.add(" ");
|
|
||||||
}
|
|
||||||
fieldnames.set(index - 1, name);
|
|
||||||
}
|
|
||||||
fieldnames.set(index - 1, name);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
//返回的List中参数列表可能会比方法参数量多,因为方法内的临时变量也会存入list中, 所以需要list的元素集合比方法的参数多
|
|
||||||
public static Map<String, List<String>> getMethodParamNames(Map<String, List<String>> map, Class clazz) {
|
|
||||||
String n = clazz.getName();
|
|
||||||
InputStream in = clazz.getResourceAsStream(n.substring(n.lastIndexOf('.') + 1) + ".class");
|
|
||||||
if (in == null) {
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
new ClassReader(Utility.readBytesThenClose(in)).accept(new MethodParamClassVisitor(Opcodes.ASM6, map), 0);
|
|
||||||
} catch (Exception e) { //无需理会
|
|
||||||
}
|
|
||||||
Class superClass = clazz.getSuperclass();
|
|
||||||
if (superClass == Object.class) {
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
return getMethodParamNames(map, superClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JsonFactory createJsonFactory(RestConvert[] converts, RestConvertCoder[] coders) {
|
public static JsonFactory createJsonFactory(RestConvert[] converts, RestConvertCoder[] coders) {
|
||||||
return createJsonFactory(-1, converts, coders);
|
return createJsonFactory(-1, converts, coders);
|
||||||
}
|
}
|
||||||
@@ -428,7 +370,7 @@ public final class Rest {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
//do nothing
|
//do nothing
|
||||||
}
|
}
|
||||||
final Map<String, List<String>> asmParamMap = namePresent ? null : MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), webSocketType);
|
final Map<String, AsmMethodBean> asmParamMap = namePresent ? null : AsmMethodBoost.getMethodBeans(webSocketType);
|
||||||
final Set<String> messageNames = new HashSet<>();
|
final Set<String> messageNames = new HashSet<>();
|
||||||
Method wildcardMethod = null;
|
Method wildcardMethod = null;
|
||||||
List<Method> mmethods = new ArrayList<>();
|
List<Method> mmethods = new ArrayList<>();
|
||||||
@@ -681,11 +623,8 @@ public final class Rest {
|
|||||||
cw2.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynSuperMessageFullName, null, "java/lang/Object", new String[]{webSocketParamName, "java/lang/Runnable"});
|
cw2.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynSuperMessageFullName, null, "java/lang/Object", new String[]{webSocketParamName, "java/lang/Runnable"});
|
||||||
cw2.visitInnerClass(newDynSuperMessageFullName, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
|
cw2.visitInnerClass(newDynSuperMessageFullName, newDynName, newDynMessageSimpleName + endfix, ACC_PUBLIC + ACC_STATIC);
|
||||||
Set<String> paramnames = new HashSet<>();
|
Set<String> paramnames = new HashSet<>();
|
||||||
String methodesc = method.getName() + ":" + Type.getMethodDescriptor(method);
|
AsmMethodBean methodBean = asmParamMap == null ? null : AsmMethodBean.get(asmParamMap, method);
|
||||||
List<String> names = asmParamMap == null ? null : asmParamMap.get(methodesc);
|
List<String> names = methodBean == null ? null : methodBean.getFieldNames();
|
||||||
if (names != null) {
|
|
||||||
while (names.remove(" ")); //删掉空元素
|
|
||||||
}
|
|
||||||
Parameter[] params = method.getParameters();
|
Parameter[] params = method.getParameters();
|
||||||
final LinkedHashMap<String, Parameter> paramap = new LinkedHashMap(); //必须使用LinkedHashMap确保顺序
|
final LinkedHashMap<String, Parameter> paramap = new LinkedHashMap(); //必须使用LinkedHashMap确保顺序
|
||||||
for (int j = 0; j < params.length; j++) { //字段列表
|
for (int j = 0; j < params.length; j++) { //字段列表
|
||||||
@@ -1896,7 +1835,7 @@ public final class Rest {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
//do nothing
|
//do nothing
|
||||||
}
|
}
|
||||||
final Map<String, List<String>> asmParamMap = namePresent ? null : MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), serviceType);
|
final Map<String, AsmMethodBean> asmParamMap = namePresent ? null : AsmMethodBoost.getMethodBeans(serviceType);
|
||||||
|
|
||||||
Map<String, byte[]> innerClassBytesMap = new LinkedHashMap<>();
|
Map<String, byte[]> innerClassBytesMap = new LinkedHashMap<>();
|
||||||
boolean containsMupload = false;
|
boolean containsMupload = false;
|
||||||
@@ -1949,11 +1888,9 @@ public final class Rest {
|
|||||||
final int maxStack = 3 + params.length;
|
final int maxStack = 3 + params.length;
|
||||||
List<int[]> varInsns = new ArrayList<>();
|
List<int[]> varInsns = new ArrayList<>();
|
||||||
int maxLocals = 4;
|
int maxLocals = 4;
|
||||||
|
|
||||||
List<String> asmParamNames = asmParamMap == null ? null : asmParamMap.get(method.getName() + ":" + Type.getMethodDescriptor(method));
|
AsmMethodBean methodBean = asmParamMap == null ? null : AsmMethodBean.get(asmParamMap, method);
|
||||||
if (asmParamNames != null) {
|
List<String> asmParamNames = methodBean == null ? null : methodBean.getFieldNames();
|
||||||
while (asmParamNames.remove(" ")); //删掉空元素
|
|
||||||
}
|
|
||||||
List<Object[]> paramlist = new ArrayList<>();
|
List<Object[]> paramlist = new ArrayList<>();
|
||||||
//解析方法中的每个参数
|
//解析方法中的每个参数
|
||||||
for (int i = 0; i < params.length; i++) {
|
for (int i = 0; i < params.length; i++) {
|
||||||
|
|||||||
@@ -560,7 +560,7 @@ public abstract class Sncp {
|
|||||||
Class clazz = serviceImplClass;
|
Class clazz = serviceImplClass;
|
||||||
Set<String> methodKeys = new HashSet<>();
|
Set<String> methodKeys = new HashSet<>();
|
||||||
do {
|
do {
|
||||||
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBean(clazz);
|
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(clazz);
|
||||||
for (final Method method : clazz.getDeclaredMethods()) {
|
for (final Method method : clazz.getDeclaredMethods()) {
|
||||||
String mk = Utility.methodKey(method);
|
String mk = Utility.methodKey(method);
|
||||||
if (methodKeys.contains(mk)) {
|
if (methodKeys.contains(mk)) {
|
||||||
@@ -571,7 +571,7 @@ public abstract class Sncp {
|
|||||||
String newMethodName = methodBoost.doMethod(cw, newDynName, FIELDPREFIX, method, null);
|
String newMethodName = methodBoost.doMethod(cw, newDynName, FIELDPREFIX, method, null);
|
||||||
if (newMethodName != null) {
|
if (newMethodName != null) {
|
||||||
String desc = Type.getMethodDescriptor(method);
|
String desc = Type.getMethodDescriptor(method);
|
||||||
AsmMethodBean methodBean = methodBeans.get(method.getName() + ":" + desc);
|
AsmMethodBean methodBean = AsmMethodBean.get(methodBeans, method);
|
||||||
String signature = null;
|
String signature = null;
|
||||||
String[] exceptions = null;
|
String[] exceptions = null;
|
||||||
if (methodBean == null) {
|
if (methodBean == null) {
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ public class RedkaleClassLoader extends URLClassLoader {
|
|||||||
"org.redkale.convert.proto",
|
"org.redkale.convert.proto",
|
||||||
"org.redkale.inject",
|
"org.redkale.inject",
|
||||||
"org.redkale.lock",
|
"org.redkale.lock",
|
||||||
|
"org.redkale.lock.spi",
|
||||||
"org.redkale.mq",
|
"org.redkale.mq",
|
||||||
"org.redkale.net",
|
"org.redkale.net",
|
||||||
"org.redkale.net.client",
|
"org.redkale.net.client",
|
||||||
|
|||||||
28
src/test/java/org/redkale/test/cache/BaseService.java
vendored
Normal file
28
src/test/java/org/redkale/test/cache/BaseService.java
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.redkale.test.cache;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
public class BaseService {
|
||||||
|
|
||||||
|
private void run1() {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void run2() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run3() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> Map<String, String> toMap(List<String> a, Set<T> set){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/test/java/org/redkale/test/cache/SimpleService.java
vendored
Normal file
13
src/test/java/org/redkale/test/cache/SimpleService.java
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.redkale.test.cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
public class SimpleService extends BaseService {
|
||||||
|
|
||||||
|
}
|
||||||
45
src/test/java/org/redkale/test/cache/TwoService.java
vendored
Normal file
45
src/test/java/org/redkale/test/cache/TwoService.java
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.redkale.test.cache;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import org.redkale.asm.AsmMethodBoost;
|
||||||
|
import org.redkale.asm.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
public class TwoService extends BaseService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void run2() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run3() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Throwable {
|
||||||
|
System.out.println("-------------------------------");
|
||||||
|
for (Method m : TwoService.class.getDeclaredMethods()) {
|
||||||
|
System.out.println(m);
|
||||||
|
}
|
||||||
|
System.out.println("-------------------------------");
|
||||||
|
for (Method m : SimpleService.class.getDeclaredMethods()) {
|
||||||
|
System.out.println(m);
|
||||||
|
}
|
||||||
|
System.out.println("-------------------------------");
|
||||||
|
for (Method m : BaseService.class.getDeclaredMethods()) {
|
||||||
|
System.out.println(m);
|
||||||
|
if(m.getName().equals("toMap")) {
|
||||||
|
System.out.println("张颠三倒四: " + Type.getType(m).getInternalName());
|
||||||
|
System.out.println("张颠三倒四: " + Type.getType(m).getDescriptor());
|
||||||
|
System.out.println("张颠三倒四: " + Type.getType(m).getClassName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("-------------------------------");
|
||||||
|
System.out.println(AsmMethodBoost.getMethodBeans(BaseService.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user