新增自动代理策略、jdk动态代理策略
This commit is contained in:
@@ -23,10 +23,10 @@ package fun.asgc.neutrino.core.aop;
|
||||
|
||||
import fun.asgc.neutrino.core.aop.proxy.Proxy;
|
||||
import fun.asgc.neutrino.core.aop.proxy.ProxyFactory;
|
||||
import fun.asgc.neutrino.core.aop.proxy.ProxyStrategy;
|
||||
import fun.asgc.neutrino.core.cache.Cache;
|
||||
import fun.asgc.neutrino.core.cache.MemoryCache;
|
||||
import fun.asgc.neutrino.core.util.Assert;
|
||||
import fun.asgc.neutrino.core.util.ClassUtil;
|
||||
import fun.asgc.neutrino.core.util.LockUtil;
|
||||
|
||||
/**
|
||||
@@ -35,16 +35,36 @@ import fun.asgc.neutrino.core.util.LockUtil;
|
||||
* @date: 2022/6/24
|
||||
*/
|
||||
public class Aop {
|
||||
private static final ProxyStrategy proxyStrategy = ProxyStrategy.SUB_CLASS_PROXY;
|
||||
private static final ProxyFactory proxyFactory = Proxy.getProxyFactory(proxyStrategy);
|
||||
private static ProxyStrategy proxyStrategy = ProxyStrategy.AUTO;
|
||||
private static final Cache<Class<?>, Object> proxyBeanCache = new MemoryCache<>();
|
||||
|
||||
public static <T> T get(Class<T> clazz) {
|
||||
Assert.notNull(proxyFactory, "代理工厂初始化异常!");
|
||||
return (T)LockUtil.doubleCheckProcess(() -> !proxyBeanCache.containsKey(clazz),
|
||||
clazz,
|
||||
() -> proxyBeanCache.set(clazz, proxyFactory.get(clazz)),
|
||||
() -> proxyBeanCache.set(clazz, getProxyFactory(clazz).get(clazz)),
|
||||
() -> proxyBeanCache.get(clazz)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取代理工厂
|
||||
* 1、如果被代理类是一个接口,则采用jdk动态代理,减少避免不必要的字节码编译开销
|
||||
* 2、其他情况则采用子类代理(AsgcProxy)
|
||||
* @return
|
||||
*/
|
||||
private static ProxyFactory getProxyFactory(Class<?> clazz) {
|
||||
if (ClassUtil.isInterface(clazz)) {
|
||||
return Proxy.getProxyFactory(ProxyStrategy.JDK_DYNAMIC_PROXY);
|
||||
}
|
||||
return Proxy.getProxyFactory(ProxyStrategy.ASGC_PROXY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置代理策略
|
||||
* @param proxyStrategy
|
||||
*/
|
||||
public static synchronized void setProxyStrategy(ProxyStrategy proxyStrategy) {
|
||||
Assert.notNull(proxyStrategy, "代理策略不能为空!");
|
||||
Aop.proxyStrategy = proxyStrategy;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -19,7 +19,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package fun.asgc.neutrino.core.aop.proxy;
|
||||
package fun.asgc.neutrino.core.aop;
|
||||
|
||||
/**
|
||||
* 代理策略
|
||||
@@ -33,8 +33,10 @@ import lombok.Getter;
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ProxyStrategy {
|
||||
// 在该模式下,代理策略由框架根据一定策略自动选择
|
||||
AUTO(0, "自动选择"),
|
||||
JDK_DYNAMIC_PROXY(1, "JDK动态代理"),
|
||||
SUB_CLASS_PROXY(2, "子类代理");
|
||||
ASGC_PROXY(2, "asgc子类代理");
|
||||
|
||||
private Integer strategy;
|
||||
private String desc;
|
||||
@@ -42,7 +42,8 @@ import java.util.stream.Stream;
|
||||
*/
|
||||
@Slf4j
|
||||
public class AsgcProxyFactory implements ProxyFactory {
|
||||
private static String classNameTemplate = "%sAsgcProxy$$%s";
|
||||
private static final String SYMBOLIC = "AsgcProxy$$";
|
||||
private static final String classNameTemplate = "%s" + SYMBOLIC + "%s";
|
||||
private static AtomicLong proxyClassCounter = new AtomicLong();
|
||||
private ProxyCompiler compiler = new ProxyCompiler();
|
||||
private ProxyClassLoader classLoader = new ProxyClassLoader();
|
||||
@@ -69,6 +70,11 @@ public class AsgcProxyFactory implements ProxyFactory {
|
||||
&& Stream.of(clazz.getConstructors()).filter(e -> e.getParameterCount() == 0).count() > 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProxyClass(Class<?> clazz) {
|
||||
return null != clazz && clazz.getSimpleName().contains(SYMBOLIC);
|
||||
}
|
||||
|
||||
private <T> T doGet(Class<T> clazz) throws ReflectiveOperationException {
|
||||
ProxyClass proxyClass = new ProxyClass(clazz);
|
||||
proxyClass.setName(generateClassName(clazz));
|
||||
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package fun.asgc.neutrino.core.aop.proxy;
|
||||
|
||||
import fun.asgc.neutrino.core.aop.Invocation;
|
||||
import fun.asgc.neutrino.core.util.ArrayUtil;
|
||||
import fun.asgc.neutrino.core.util.Assert;
|
||||
import fun.asgc.neutrino.core.util.ClassUtil;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
/**
|
||||
* JDK动态代理
|
||||
* @author: aoshiguchen
|
||||
* @date: 2022/6/29
|
||||
*/
|
||||
public class JdkDynamicProxyFactory implements ProxyFactory {
|
||||
|
||||
@Override
|
||||
public <T> T get(Class<T> clazz) {
|
||||
Assert.notNull(clazz, "被代理类不能为空!");
|
||||
Assert.isTrue(canProxy(clazz), String.format("类[%s]无法被代理!", clazz.getName()));
|
||||
try {
|
||||
return doGet(clazz);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private <T> T doGet(Class<T> clazz) throws ReflectiveOperationException {
|
||||
if (ClassUtil.isInterface(clazz)) {
|
||||
return (T) Proxy.newProxyInstance(clazz.getClassLoader(),
|
||||
new Class[]{clazz},
|
||||
new JdkDynamicProxy(null)
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProxy(Class<?> clazz) {
|
||||
return ClassUtil.isInterface(clazz) || ArrayUtil.notEmpty(clazz.getInterfaces());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProxyClass(Class<?> clazz) {
|
||||
return Proxy.isProxyClass(clazz);
|
||||
}
|
||||
|
||||
private static class JdkDynamicProxy implements InvocationHandler {
|
||||
private Object target;
|
||||
public JdkDynamicProxy(Object target) {
|
||||
this.target = target;
|
||||
}
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
Long methodId = ProxyCache.setMethod(method);
|
||||
Invocation inv = new Invocation(methodId,this, () -> {
|
||||
if (null != target) {
|
||||
try {
|
||||
return method.invoke(target, args);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}, args);
|
||||
inv.invoke();
|
||||
return inv.getReturnValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,8 @@
|
||||
*/
|
||||
package fun.asgc.neutrino.core.aop.proxy;
|
||||
|
||||
import fun.asgc.neutrino.core.aop.ProxyStrategy;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author: aoshiguchen
|
||||
@@ -28,10 +30,12 @@ package fun.asgc.neutrino.core.aop.proxy;
|
||||
*/
|
||||
public class Proxy {
|
||||
private static final ProxyFactory subClassProxyFactory = new AsgcProxyFactory();
|
||||
private static final ProxyFactory jdkDynamicProxyFactory = new JdkDynamicProxyFactory();
|
||||
|
||||
public static ProxyFactory getProxyFactory(ProxyStrategy strategy) {
|
||||
switch (strategy) {
|
||||
case SUB_CLASS_PROXY: return subClassProxyFactory;
|
||||
case ASGC_PROXY: return subClassProxyFactory;
|
||||
case JDK_DYNAMIC_PROXY: return jdkDynamicProxyFactory;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,4 +41,11 @@ public interface ProxyFactory {
|
||||
* @return
|
||||
*/
|
||||
boolean canProxy(Class<?> clazz);
|
||||
|
||||
/**
|
||||
* 判断指定类是否由当前代理策略产生
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
boolean isProxyClass(Class<?> clazz);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user