Resource支持@name、@type

This commit is contained in:
redkale
2023-03-14 10:56:19 +08:00
parent 42201c7c11
commit 1edd256028
12 changed files with 245 additions and 76 deletions

View File

@@ -8,6 +8,10 @@ package org.redkale.annotation;
import java.lang.annotation.*;
/**
* &#64;Resource(name = "$") 表示资源name采用所属对象的name <br>
* &#64;Resource(name = "@name") 表示资源对象自身的name <br>
* &#64;Resource(name = "@type") 表示资源对象自身的类型 <br>
*
* @since Common Annotations 1.0
*
* @since 2.8.0
@@ -15,7 +19,7 @@ import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Resource {
/**
* 是否必须存在
*
@@ -26,7 +30,13 @@ public @interface Resource {
public boolean required() default true;
/**
* 资源名称
* 资源名称 <br>
* <blockquote><pre>
* name规则:
* 1: "$"有特殊含义, 表示资源本身,"$"不能单独使用
* 2: "@name"、"@type"有特殊含义
* 3: 只能是字母、数字、(短横)-、(下划线)_、点(.)的组合
* </pre></blockquote>
*
* @return String
*/

View File

@@ -67,9 +67,9 @@ public abstract class DispatcherServlet<K extends Serializable, C extends Contex
protected void putServlet(S servlet) {
servletLock.lock();
try {
Set<S> newservlets = new HashSet<>(servlets);
newservlets.add(servlet);
this.servlets = newservlets;
Set<S> newServlets = new HashSet<>(servlets);
newServlets.add(servlet);
this.servlets = newServlets;
} finally {
servletLock.unlock();
}
@@ -78,9 +78,9 @@ public abstract class DispatcherServlet<K extends Serializable, C extends Contex
protected void removeServlet(S servlet) {
servletLock.lock();
try {
Set<S> newservlets = new HashSet<>(servlets);
newservlets.remove(servlet);
this.servlets = newservlets;
Set<S> newServlets = new HashSet<>(servlets);
newServlets.remove(servlet);
this.servlets = newServlets;
doAfterRemove(servlet);
} finally {
servletLock.unlock();
@@ -118,9 +118,9 @@ public abstract class DispatcherServlet<K extends Serializable, C extends Contex
protected void putMapping(K key, S servlet) {
mappingLock.lock();
try {
Map<K, S> newmappings = new HashMap<>(mappings);
newmappings.put(key, servlet);
this.mappings = newmappings;
Map<K, S> newMappings = new HashMap<>(mappings);
newMappings.put(key, servlet);
this.mappings = newMappings;
} finally {
mappingLock.unlock();
}
@@ -144,14 +144,14 @@ public abstract class DispatcherServlet<K extends Serializable, C extends Contex
mappingLock.lock();
try {
List<K> keys = new ArrayList<>();
Map<K, S> newmappings = new HashMap<>(mappings);
for (Map.Entry<K, S> en : newmappings.entrySet()) {
Map<K, S> newMappings = new HashMap<>(mappings);
for (Map.Entry<K, S> en : newMappings.entrySet()) {
if (en.getValue().equals(servlet)) {
keys.add(en.getKey());
}
}
for (K key : keys) newmappings.remove(key);
this.mappings = newmappings;
for (K key : keys) newMappings.remove(key);
this.mappings = newMappings;
doAfterRemove(servlet);
} finally {
mappingLock.unlock();
@@ -176,7 +176,7 @@ public abstract class DispatcherServlet<K extends Serializable, C extends Contex
if (!filters.isEmpty()) {
Collections.sort(filters);
for (Filter<C, R, P> filter : filters) {
filter.init(context, config);
filter.init(context, filter._conf);
}
this.headFilter = filters.get(0);
Filter<C, R, P> filter = this.headFilter;
@@ -191,13 +191,13 @@ public abstract class DispatcherServlet<K extends Serializable, C extends Contex
}
@Override
@SuppressWarnings("unchecked")
@SuppressWarnings("unchecked") //Servlet由子类来销毁
public void destroy(C context, AnyValue config) {
filtersLock.lock();
try {
if (!filters.isEmpty()) {
for (Filter filter : filters) {
filter.destroy(context, config);
filter.destroy(context, filter._conf);
}
}
} finally {
@@ -307,6 +307,14 @@ public abstract class DispatcherServlet<K extends Serializable, C extends Contex
servlet._conf = conf;
}
protected AnyValue getFilterConf(Filter filter) {
return filter._conf;
}
protected void setFilterConf(Filter filter, AnyValue conf) {
filter._conf = conf;
}
public List<S> getServlets() {
return new ArrayList<>(servlets);
}

View File

@@ -7,12 +7,12 @@ package org.redkale.net;
import java.io.*;
import java.net.*;
import java.nio.charset.Charset;
import java.nio.charset.*;
import java.util.*;
import java.util.concurrent.atomic.LongAdder;
import java.util.concurrent.atomic.*;
import java.util.logging.*;
import javax.net.ssl.SSLContext;
import org.redkale.boot.Application;
import javax.net.ssl.*;
import org.redkale.boot.*;
import static org.redkale.net.AsyncGroup.UDP_BUFFER_CAPACITY;
import org.redkale.net.Filter;
import org.redkale.util.*;
@@ -483,6 +483,16 @@ public abstract class Server<K extends Serializable, C extends Context, R extend
return this.dispatcher.containsFilter(filterClassName);
}
/**
* 销毁Servlet
*
* @param <T> 泛型
* @param filter Filter
*/
public <T extends Filter> void destroyFilter(T filter) {
filter.destroy(context, this.dispatcher.getFilterConf(filter));
}
/**
* 判断是否存在Servlet
*

View File

@@ -5,21 +5,22 @@
*/
package org.redkale.net.sncp;
import java.io.IOException;
import java.io.*;
import java.lang.reflect.*;
import java.nio.channels.CompletionHandler;
import java.nio.channels.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import org.redkale.annotation.NonBlocking;
import java.util.concurrent.atomic.*;
import java.util.logging.*;
import org.redkale.annotation.*;
import static org.redkale.asm.ClassWriter.COMPUTE_FRAMES;
import org.redkale.asm.*;
import static org.redkale.asm.Opcodes.*;
import org.redkale.asm.Type;
import org.redkale.convert.*;
import org.redkale.convert.bson.BsonFactory;
import org.redkale.service.Service;
import org.redkale.convert.Reader;
import org.redkale.convert.bson.*;
import org.redkale.service.*;
import org.redkale.util.*;
/**
@@ -159,11 +160,12 @@ public final class SncpDynServlet extends SncpServlet {
java.lang.reflect.Type handlerResultType = null;
try {
final Class[] paramClasses = method.getParameterTypes();
java.lang.reflect.Type[] genericParams = method.getGenericParameterTypes();
for (int i = 0; i < paramClasses.length; i++) { //反序列化方法的每个参数
if (CompletionHandler.class.isAssignableFrom(paramClasses[i])) {
handlerFuncIndex = i;
handlerFuncClass = paramClasses[i];
java.lang.reflect.Type handlerType = TypeToken.getGenericType(method.getTypeParameters()[i], service.getClass());
java.lang.reflect.Type handlerType = TypeToken.getGenericType(genericParams[i], service.getClass());
if (handlerType instanceof Class) {
handlerResultType = Object.class;
} else if (handlerType instanceof ParameterizedType) {

View File

@@ -3,13 +3,13 @@
*/
package org.redkale.net.sncp;
import java.lang.annotation.Annotation;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.net.*;
import java.nio.channels.CompletionHandler;
import java.nio.channels.*;
import java.util.*;
import java.util.concurrent.*;
import org.redkale.convert.Convert;
import org.redkale.convert.*;
import org.redkale.mq.*;
import static org.redkale.net.sncp.Sncp.loadMethodActions;
import org.redkale.service.*;
@@ -185,6 +185,7 @@ public final class SncpServiceInfo<T extends Service> {
Class handlerFuncClass = null;
java.lang.reflect.Type handlerResultType = null;
Class<?>[] params = method.getParameterTypes();
Type[] genericParams = method.getGenericParameterTypes();
for (int i = 0; i < params.length; i++) {
if (CompletionHandler.class.isAssignableFrom(params[i])) {
if (Future.class.isAssignableFrom(method.getReturnType())) {
@@ -196,7 +197,7 @@ public final class SncpServiceInfo<T extends Service> {
Sncp.checkAsyncModifier(params[i], method);
handlerFuncIndex = i;
handlerFuncClass = paramClasses[i];
java.lang.reflect.Type handlerType = TypeToken.getGenericType(method.getTypeParameters()[i], serviceImplClass);
java.lang.reflect.Type handlerType = TypeToken.getGenericType(genericParams[i], serviceImplClass);
if (handlerType instanceof Class) {
handlerResultType = Object.class;
} else if (handlerType instanceof ParameterizedType) {

View File

@@ -9,8 +9,7 @@ import java.util.concurrent.*;
import org.redkale.annotation.Resource;
import org.redkale.boot.Application;
import org.redkale.net.WorkThread;
import org.redkale.net.sncp.Sncp;
import org.redkale.util.ThreadHashExecutor;
import org.redkale.util.*;
/**
*
@@ -22,13 +21,23 @@ public abstract class AbstractService implements Service {
@Resource(name = Application.RESNAME_APP_EXECUTOR, required = false)
private ExecutorService workExecutor;
@Resource(name = ResourceFactory.RESOURCE_SELF_NAME, required = false)
private String serviceName;
@Resource(name = ResourceFactory.RESOURCE_SELF_TYPE, required = false)
private Class serviceType;
protected String serviceName() {
return serviceName;
}
/**
* 当前Service类的原始Service类型 由于Service会动态重载所以getClass()得到的不是原始Service类型
*
* @return Class
*/
protected Class serviceType() {
return Sncp.isSncpDyn(this) && getClass().getSimpleName().startsWith("_Dyn") ? getClass().getSuperclass() : getClass();
return serviceType;
}
/**

View File

@@ -5,14 +5,14 @@
*/
package org.redkale.util;
import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
import java.lang.annotation.*;
import java.lang.ref.*;
import java.lang.reflect.*;
import java.math.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;
import java.util.function.*;
import java.util.logging.*;
import org.redkale.annotation.*;
@@ -28,8 +28,9 @@ import org.redkale.convert.*;
* 如果没有&#64;Resource且对象实现了Resourcable, 则会取对象的resourceName()方法值
* <blockquote><pre>
* name规则:
* 1: "$"有特殊含义, 不能表示"$"资源本身
* 2: 只能是字母、数字、(短横)-、(下划线)_、点(.)的组合
* 1: "$"有特殊含义, 表示资源本身,"$"不能单独使用
* 2: "@name"、"@type"有特殊含义
* 3: 只能是字母、数字、(短横)-、(下划线)_、点(.)的组合
* </pre></blockquote>
* <p>
* 详情见: https://redkale.org
@@ -41,6 +42,10 @@ public final class ResourceFactory {
public static final String RESOURCE_PARENT_NAME = "$";
public static final String RESOURCE_SELF_NAME = "@name";
public static final String RESOURCE_SELF_TYPE = "@type";
private static final boolean skipCheckRequired = Boolean.getBoolean("redkale.resource.skip.check");
private static final Logger logger = Logger.getLogger(ResourceFactory.class.getSimpleName());
@@ -128,7 +133,8 @@ public final class ResourceFactory {
* <blockquote><pre>
* name规则:
* 1: "$"有特殊含义, 表示资源本身,"$"不能单独使用
* 2: 只能是字母、数字、(短横)-、(下划线)_、点(.)、小括号、中括号的组合
* 2: "@name"、"@type"有特殊含义
* 3: 只能是字母、数字、(短横)-、(下划线)_、点(.)的组合
* </pre></blockquote>
*
* @param name String
@@ -544,6 +550,58 @@ public final class ResourceFactory {
if (clz != null && !clz.isPrimitive() && val != null && !clz.isAssignableFrom(val.getClass())) {
throw new RedkaleException(clz + "not isAssignableFrom (" + val + ") class " + val.getClass());
}
String clzname = clz != null ? clz.getName() : "java.lang.String";
if (val != null && !clzname.startsWith("java.") && !clzname.startsWith("javax.")
&& !clzname.startsWith("jdk.") && !clzname.startsWith("sun.")) {
Class c = val.getClass();
do {
if (java.lang.Enum.class.isAssignableFrom(c)) {
break;
}
final String cname = c.getName();
if (cname.startsWith("java.") || cname.startsWith("javax.")
|| cname.startsWith("jdk.") || cname.startsWith("sun.")) {
break;
}
if (cname.indexOf('/') < 0) {//排除内部类, 如:JsonConvert$$Lambda$87/0x0000000100197440-
RedkaleClassLoader.putReflectionDeclaredFields(cname);
}
for (Field field : c.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
if (Modifier.isFinal(field.getModifiers())) {
continue;
}
Resource rc = field.getAnnotation(Resource.class);
if (rc == null) {
continue;
}
if (!rc.name().equals(RESOURCE_SELF_NAME) && !rc.name().equals(RESOURCE_SELF_TYPE)) {
continue;
}
final Class classType = field.getType();
RedkaleClassLoader.putReflectionField(cname, field);
try {
if (rc.name().equals(RESOURCE_SELF_NAME)) {
if (classType != String.class) {
throw new ResourceInjectException("resource(type=" + c.getSimpleName() + ".class, field=" + field.getName() + ", name='" + rc.name() + "') must be String ");
}
field.setAccessible(true);
field.set(val, name);
} else if (rc.name().equals(RESOURCE_SELF_TYPE)) {
if (classType != Type.class && classType != Class.class) {
throw new ResourceInjectException("resource(type=" + c.getSimpleName() + ".class, field=" + field.getName() + ", name='" + rc.name() + "') must be Type or Class ");
}
field.setAccessible(true);
field.set(val, classType == Class.class ? TypeToken.typeToClass(clazz) : clazz);
}
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new ResourceInjectException("resource(type=" + c.getSimpleName() + ".class, field=" + field.getName() + ", name='" + rc.name() + "') register error ", e);
}
}
} while ((c = c.getSuperclass()) != Object.class);
}
ConcurrentHashMap<String, ResourceEntry> map = this.store.computeIfAbsent(clazz, k -> new ConcurrentHashMap());
ResourceEntry re = map.get(name);
if (re == null) {
@@ -828,6 +886,9 @@ public final class ResourceFactory {
consumer.accept(srcObj, field);
}
String tname = rc1 == null ? rc2.name() : rc1.name();
if (tname.equals(RESOURCE_SELF_NAME) || tname.equals(RESOURCE_SELF_TYPE)) {
continue;
}
if (tname.contains(RESOURCE_PARENT_NAME)) {
Resource res1 = srcObj.getClass().getAnnotation(Resource.class);
javax.annotation.Resource res2 = srcObj.getClass().getAnnotation(javax.annotation.Resource.class);