cn.t.util.common.ReflectUtil Maven / Gradle / Ivy
package cn.t.util.common;
import cn.t.util.common.proxy.ProxyCallback;
import cn.t.util.common.proxy.ProxyConfig;
import net.sf.cglib.proxy.*;
import java.lang.reflect.*;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* JDK与Cglib区别
* 1.Jdk需要声明接口 Cglib不需要生成接口
* 2.Jdk代理实力只能用接口类型赋值, Cglib没有此限制
* 3.在Jdk代理类中调用另外一个方法时不会再进切面, 而在Cglib类中调用另外一个方法依然会进切面
*
* 总结: Cglib更方便使用
*/
public class ReflectUtil {
private static final Map, Method[]> declaredMethodsCache =
new ConcurrentHashMap<>(256);
private static final Method[] NO_METHODS = {};
public static Object generateCglibProxy(Object target, ProxyConfig config) {
CglibProxy proxy = new CglibProxy(target, config.getProxyCallback());
CglibProxyCallbackFilter filter = new CglibProxyCallbackFilter(proxy, config);
Enhancer enhancer = new Enhancer();
//设置要被代理的类
enhancer.setSuperclass(target.getClass());
//设置多个拦截器(setCallbacks中的拦截器顺序一定要和callbackFilter中的顺序一致)
enhancer.setCallbacks(new Callback[]{proxy, NoOp.INSTANCE});
enhancer.setCallbackFilter(filter);
return enhancer.create();
}
public static Object generateJdkProxy(Object target, ProxyConfig config) {
JdkProxy jdkProxy = new JdkProxy(target, config);
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), jdkProxy);
}
/**
* 获取泛型类型
* @param object xxx
* @param parameterizedSuperclass xxx
* @param typeParamName xxx
* @return xxx
*/
public static Class findTypeParam(final Object object, Class> parameterizedSuperclass, String typeParamName) {
final Class thisClass = object.getClass();
Class currentClass = thisClass;
for (; ; ) {
if (currentClass.getSuperclass() == parameterizedSuperclass) {
int typeParamIndex = -1;
TypeVariable>[] typeParams = currentClass.getSuperclass().getTypeParameters();
for (int i = 0; i < typeParams.length; i++) {
if (typeParamName.equals(typeParams[i].getName())) {
typeParamIndex = i;
break;
}
}
if (typeParamIndex < 0) {
throw new IllegalStateException(
"unknown type parameter '" + typeParamName + "': " + parameterizedSuperclass);
}
Type genericSuperType = currentClass.getGenericSuperclass();
if (!(genericSuperType instanceof ParameterizedType)) {
return Object.class;
}
Type[] actualTypeParams = ((ParameterizedType) genericSuperType).getActualTypeArguments();
Type actualTypeParam = actualTypeParams[typeParamIndex];
if (actualTypeParam instanceof ParameterizedType) {
actualTypeParam = ((ParameterizedType) actualTypeParam).getRawType();
}
if (actualTypeParam instanceof Class) {
return (Class>) actualTypeParam;
}
if (actualTypeParam instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) actualTypeParam).getGenericComponentType();
if (componentType instanceof ParameterizedType) {
componentType = ((ParameterizedType) componentType).getRawType();
}
if (componentType instanceof Class) {
return Array.newInstance((Class>) componentType, 0).getClass();
}
}
if (actualTypeParam instanceof TypeVariable) {
// Resolved type parameter points to another type parameter.
TypeVariable> v = (TypeVariable>) actualTypeParam;
currentClass = thisClass;
if (!(v.getGenericDeclaration() instanceof Class)) {
return Object.class;
}
parameterizedSuperclass = (Class>) v.getGenericDeclaration();
typeParamName = v.getName();
if (parameterizedSuperclass.isAssignableFrom(thisClass)) {
continue;
} else {
return Object.class;
}
}
throw new IllegalStateException("cannot determine the type of the type parameter '" + thisClass + "': " + typeParamName);
}
currentClass = currentClass.getSuperclass();
if (currentClass == null) {
throw new IllegalStateException("cannot determine the type of the type parameter '" + thisClass + "': " + typeParamName);
}
}
}
public static Method findMethod(Class> clazz, String name, Class>... paramTypes) {
Assert.notNull(clazz, "Class must not be null");
Assert.notNull(name, "Method name must not be null");
Class> searchType = clazz;
while (searchType != null) {
Method[] methods = (searchType.isInterface() ? searchType.getMethods() : getDeclaredMethods(searchType));
for (Method method : methods) {
if (name.equals(method.getName()) &&
(paramTypes == null || Arrays.equals(paramTypes, method.getParameterTypes()))) {
return method;
}
}
searchType = searchType.getSuperclass();
}
return null;
}
private static Method[] getDeclaredMethods(Class> clazz) {
Assert.notNull(clazz, "Class must not be null");
Method[] result = declaredMethodsCache.get(clazz);
if (result == null) {
Method[] declaredMethods = clazz.getDeclaredMethods();
List defaultMethods = findConcreteMethodsOnInterfaces(clazz);
if (defaultMethods != null) {
result = new Method[declaredMethods.length + defaultMethods.size()];
System.arraycopy(declaredMethods, 0, result, 0, declaredMethods.length);
int index = declaredMethods.length;
for (Method defaultMethod : defaultMethods) {
result[index] = defaultMethod;
index++;
}
} else {
result = declaredMethods;
}
declaredMethodsCache.put(clazz, (result.length == 0 ? NO_METHODS : result));
}
return result;
}
private static List findConcreteMethodsOnInterfaces(Class> clazz) {
List result = null;
for (Class> ifc : clazz.getInterfaces()) {
for (Method ifcMethod : ifc.getMethods()) {
if (!Modifier.isAbstract(ifcMethod.getModifiers())) {
if (result == null) {
result = new LinkedList<>();
}
result.add(ifcMethod);
}
}
}
return result;
}
public static boolean isPublicStaticFinal(Field field) {
int modifiers = field.getModifiers();
return (Modifier.isPublic(modifiers) && isPublic(modifiers) && isFinal(modifiers));
}
public static boolean isPublic(Field field) {
int modifiers = field.getModifiers();
return Modifier.isPublic(modifiers);
}
public static boolean isPublic(int modifiers) {
return Modifier.isPublic(modifiers);
}
public static boolean isFinal(Field field) {
int modifiers = field.getModifiers();
return Modifier.isFinal(modifiers);
}
public static boolean isFinal(int modifiers) {
return Modifier.isFinal(modifiers);
}
/**
* 代理
*/
private interface BaseProxy {
default boolean apply(Method method, String... methods) {
if (methods == null || methods.length == 0) {
return false;
} else {
String methodName = method.getName();
for (String m : methods) {
if (methodName.equals(m)) {
return true;
}
}
return false;
}
}
}
private static class CglibProxyCallbackFilter implements CallbackFilter {
private BaseProxy proxy;
private ProxyConfig config;
private CglibProxyCallbackFilter(BaseProxy proxy, ProxyConfig config) {
this.proxy = proxy;
this.config = config;
}
@Override
public int accept(Method method) {
return proxy.apply(method, config.getInterceptMethods()) ? 0 : 1;
}
}
/**
* cglib代理
*/
private static class CglibProxy implements MethodInterceptor, BaseProxy {
private Object target;
private ProxyCallback callback;
public CglibProxy(Object target, ProxyCallback callback) {
this.target = target;
this.callback = callback;
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
callback.before(obj, method, args);
Object result = methodProxy.invokeSuper(obj, args);
callback.after(result);
return result;
}
}
/**
* jdk代理
*/
private static class JdkProxy implements java.lang.reflect.InvocationHandler, BaseProxy {
private Object target;
private ProxyConfig config;
private JdkProxy(Object target, ProxyConfig config) {
this.target = target;
this.config = config;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
boolean apply = apply(method, config.getInterceptMethods());
if (apply) {
config.getProxyCallback().before(target, method, args);
}
Object result = method.invoke(target, args);
if (apply) {
config.getProxyCallback().after(result);
}
return result;
}
}
}