新增自动代理策略、jdk动态代理策略

This commit is contained in:
aoshiguchen
2022-06-29 21:14:21 +08:00
parent 600dfb1b2a
commit 899d90806c
6 changed files with 142 additions and 9 deletions
@@ -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;
}
}
@@ -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));
@@ -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);
}