enhance aop

This commit is contained in:
Looly 2019-09-27 23:20:43 +08:00
parent 5b5645cbbb
commit 45609bc22b
8 changed files with 280 additions and 250 deletions

View File

@ -9,7 +9,7 @@ import java.lang.reflect.Method;
* @author ted.L * @author ted.L
* @since 4.18 * @since 4.18
*/ */
public interface Aspect{ public interface Aspect {
/** /**
* 目标方法执行前的操作 * 目标方法执行前的操作
@ -24,15 +24,15 @@ public interface Aspect{
/** /**
* 目标方法执行后的操作 * 目标方法执行后的操作
* 如果 target.method 抛出异常且 * 如果 target.method 抛出异常且
* @see Aspect#afterException 返回true,则不会执行此操作
* 如果
* @see Aspect#afterException 返回false,则无论target.method是否抛出异常均会执行此操作
* *
* @param target 目标对象 * @param target 目标对象
* @param method 目标方法 * @param method 目标方法
* @param args 参数 * @param args 参数
* @param returnVal 目标方法执行返回值 * @param returnVal 目标方法执行返回值
* @return 是否允许返回值接下来的操作 * @return 是否允许返回值接下来的操作
* @see Aspect#afterException 返回true,则不会执行此操作
* 如果
* @see Aspect#afterException 返回false,则无论target.method是否抛出异常均会执行此操作
*/ */
boolean after(Object target, Method method, Object[] args, Object returnVal); boolean after(Object target, Method method, Object[] args, Object returnVal);

View File

@ -7,37 +7,41 @@ import java.lang.reflect.Method;
* 简单切面类不做任何操作<br> * 简单切面类不做任何操作<br>
* 可以继承此类实现自己需要的方法即可 * 可以继承此类实现自己需要的方法即可
* *
* @author Looly * @author Looly, ted.L
* @author ted.L
*
*/ */
public abstract class SimpleAspect implements Aspect, Serializable{ public class SimpleAspect implements Aspect, Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/**
* @see Aspect#before(Object, Method, Object[])
* @return 是否继续执行接下来的操作 默认值true
*/
@Override @Override
public boolean before(Object target, Method method, Object[] args) { public boolean before(Object target, Method method, Object[] args) {
//继承此类后实现此方法 //继承此类后实现此方法
return true; return true;
} }
/** /**
* @see Aspect#after(Object, Method, Object[], Object) * 目标方法执行后的操作
* @return 是否允许返回值接下来的操作 默认值true * 如果 target.method 抛出异常且
*
* @param target 目标对象
* @param method 目标方法
* @param args 参数
* @return 是否允许返回值接下来的操作
* @see Aspect#afterException 返回true,则不会执行此操作
* 如果
* @see Aspect#afterException 返回false,则无论target.method是否抛出异常均会执行此操作
*/ */
public boolean after(Object target, Method method, Object[] args) {
//继承此类后实现此方法
return after(target, method, args, null);
}
@Override @Override
public boolean after(Object target, Method method, Object[] args, Object returnVal) { public boolean after(Object target, Method method, Object[] args, Object returnVal) {
//继承此类后实现此方法 //继承此类后实现此方法
return true; return true;
} }
/**
* @see Aspect#afterException(Object, Method, Object[], Throwable)
* @return 是否允许抛出异常 默认值true
*/
@Override @Override
public boolean afterException(Object target, Method method, Object[] args, Throwable e) { public boolean afterException(Object target, Method method, Object[] args, Throwable e) {
//继承此类后实现此方法 //继承此类后实现此方法

View File

@ -8,8 +8,8 @@ import cn.hutool.core.util.StrUtil;
/** /**
* 通过日志打印方法的执行时间的切面 * 通过日志打印方法的执行时间的切面
* @author Looly
* *
* @author Looly
*/ */
public class TimeIntervalAspect extends SimpleAspect { public class TimeIntervalAspect extends SimpleAspect {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -24,7 +24,11 @@ public class TimeIntervalAspect extends SimpleAspect {
@Override @Override
public boolean after(Object target, Method method, Object[] args, Object returnVal) { public boolean after(Object target, Method method, Object[] args, Object returnVal) {
Console.log("Method [{}.{}] execute spend [{}]ms return value [{}]", target.getClass().getName(), method.getName(), interval.intervalMs(), StrUtil.toString(returnVal)); Console.log("Method [{}.{}] execute spend [{}]ms return value [{}]",
target.getClass().getName(), //
method.getName(), //
interval.intervalMs(), //
returnVal);
return true; return true;
} }
} }

View File

@ -1,20 +1,17 @@
package cn.hutool.aop.interceptor; package cn.hutool.aop.interceptor;
import cn.hutool.aop.aspects.Aspect;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import cn.hutool.aop.aspects.Aspect;
import cn.hutool.core.exceptions.UtilException;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/** /**
* Cglib实现的动态代理切面 * Cglib实现的动态代理切面
* *
* @author looly * @author looly, ted.L
* @author ted.L
*
*/ */
public class CglibInterceptor implements MethodInterceptor, Serializable { public class CglibInterceptor implements MethodInterceptor, Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -40,22 +37,20 @@ public class CglibInterceptor implements MethodInterceptor, Serializable {
@Override @Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object result = null; Object result = null;
// 开始前回调
if (aspect.before(target, method, args)) { if (aspect.before(target, method, args)) {
try { try {
// result = ReflectUtil.invoke(target, method, args);
result = proxy.invokeSuper(obj, args); result = proxy.invokeSuper(obj, args);
} catch (UtilException e) { } catch (InvocationTargetException e) {
final Throwable cause = e.getCause(); // 异常回调只捕获业务代码导致的异常而非反射导致的异常
if (!(e.getCause() instanceof InvocationTargetException)) { if (aspect.afterException(target, method, args, e.getTargetException())) {
// 其它异常属于代理的异常直接抛出
throw e; throw e;
} }
if(aspect.afterException(target, method, args, ((InvocationTargetException) cause).getTargetException())){ }
throw e;
} }
} // 结束执行回调
}
if (aspect.after(target, method, args, result)) { if (aspect.after(target, method, args, result)) {
return result; return result;
} }

View File

@ -7,6 +7,7 @@ import java.lang.reflect.Method;
import cn.hutool.aop.aspects.Aspect; import cn.hutool.aop.aspects.Aspect;
import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.ReflectUtil;
/** /**
@ -14,9 +15,8 @@ import cn.hutool.core.util.ReflectUtil;
* *
* @author Looly * @author Looly
* @author ted.L * @author ted.L
*
*/ */
public class JdkInterceptor implements InvocationHandler, Serializable{ public class JdkInterceptor implements InvocationHandler, Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private Object target; private Object target;
@ -42,20 +42,22 @@ public class JdkInterceptor implements InvocationHandler, Serializable{
final Object target = this.target; final Object target = this.target;
final Aspect aspect = this.aspect; final Aspect aspect = this.aspect;
Object result = null; Object result = null;
// 开始前回调
if (aspect.before(target, method, args)) { if (aspect.before(target, method, args)) {
ReflectUtil.setAccessible(method);
try { try {
result = ReflectUtil.invoke(target, method, args); result = method.invoke(ClassUtil.isStatic(method) ? null : target, args);
} catch (UtilException e) { } catch (InvocationTargetException e) {
final Throwable cause = e.getCause(); // 异常回调只捕获业务代码导致的异常而非反射导致的异常
if (!(e.getCause() instanceof InvocationTargetException)) { if (aspect.afterException(target, method, args, e.getTargetException())) {
// 其它异常属于代理的异常直接抛出
throw e;
}
if(aspect.afterException(target, method, args, ((InvocationTargetException) cause).getTargetException())){
throw e; throw e;
} }
} }
} }
// 结束执行回调
if (aspect.after(target, method, args, result)) { if (aspect.after(target, method, args, result)) {
return result; return result;
} }

View File

@ -8,14 +8,16 @@ import cn.hutool.aop.interceptor.JdkInterceptor;
* JDK实现的切面代理 * JDK实现的切面代理
* *
* @author looly * @author looly
*
*/ */
public class JdkProxyFactory extends ProxyFactory{ public class JdkProxyFactory extends ProxyFactory {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T proxy(T target, Aspect aspect) { public <T> T proxy(T target, Aspect aspect) {
return (T) ProxyUtil.newProxyInstance(target.getClass().getClassLoader(), new JdkInterceptor(target, aspect), target.getClass().getInterfaces()); return (T) ProxyUtil.newProxyInstance(//
target.getClass().getClassLoader(), //
new JdkInterceptor(target, aspect), //
target.getClass().getInterfaces());
} }
} }

View File

@ -1,5 +1,6 @@
package cn.hutool.aop.test; package cn.hutool.aop.test;
import cn.hutool.core.lang.Console;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -10,7 +11,6 @@ import cn.hutool.aop.aspects.TimeIntervalAspect;
* AOP模块单元测试 * AOP模块单元测试
* *
* @author Looly * @author Looly
*
*/ */
public class AopTest { public class AopTest {
@ -40,7 +40,6 @@ public class AopTest {
* 有接口 * 有接口
* *
* @author looly * @author looly
*
*/ */
static class Cat implements Animal { static class Cat implements Animal {
@ -51,7 +50,7 @@ public class AopTest {
@Override @Override
public void seize() { public void seize() {
System.out.println("抓了条鱼"); Console.log("抓了条鱼");
} }
} }
@ -59,7 +58,6 @@ public class AopTest {
* 无接口 * 无接口
* *
* @author looly * @author looly
*
*/ */
static class Dog { static class Dog {
public String eat() { public String eat() {
@ -67,7 +65,7 @@ public class AopTest {
} }
public void seize() { public void seize() {
System.out.println("抓了只鸡"); Console.log("抓了只鸡");
} }
} }
} }

View File

@ -1,13 +1,5 @@
package cn.hutool.core.util; package cn.hutool.core.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.exceptions.UtilException;
@ -15,6 +7,15 @@ import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Filter; import cn.hutool.core.lang.Filter;
import cn.hutool.core.lang.SimpleCache; import cn.hutool.core.lang.SimpleCache;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/** /**
* 反射工具类 * 反射工具类
* *
@ -23,14 +24,21 @@ import cn.hutool.core.lang.SimpleCache;
*/ */
public class ReflectUtil { public class ReflectUtil {
/** 构造对象缓存 */ /**
* 构造对象缓存
*/
private static final SimpleCache<Class<?>, Constructor<?>[]> CONSTRUCTORS_CACHE = new SimpleCache<>(); private static final SimpleCache<Class<?>, Constructor<?>[]> CONSTRUCTORS_CACHE = new SimpleCache<>();
/** 字段缓存 */ /**
* 字段缓存
*/
private static final SimpleCache<Class<?>, Field[]> FIELDS_CACHE = new SimpleCache<>(); private static final SimpleCache<Class<?>, Field[]> FIELDS_CACHE = new SimpleCache<>();
/** 方法缓存 */ /**
* 方法缓存
*/
private static final SimpleCache<Class<?>, Method[]> METHODS_CACHE = new SimpleCache<>(); private static final SimpleCache<Class<?>, Method[]> METHODS_CACHE = new SimpleCache<>();
// --------------------------------------------------------------------------------------------------------- Constructor // --------------------------------------------------------------------------------------------------------- Constructor
/** /**
* 查找类中的指定参数的构造方法如果找到构造方法会自动设置可访问为true * 查找类中的指定参数的构造方法如果找到构造方法会自动设置可访问为true
* *
@ -51,7 +59,7 @@ public class ReflectUtil {
pts = constructor.getParameterTypes(); pts = constructor.getParameterTypes();
if (ClassUtil.isAllAssignableFrom(pts, parameterTypes)) { if (ClassUtil.isAllAssignableFrom(pts, parameterTypes)) {
// 构造可访问 // 构造可访问
constructor.setAccessible(true); setAccessible(constructor);
return (Constructor<T>) constructor; return (Constructor<T>) constructor;
} }
} }
@ -91,6 +99,7 @@ public class ReflectUtil {
} }
// --------------------------------------------------------------------------------------------------------- Field // --------------------------------------------------------------------------------------------------------- Field
/** /**
* 查找指定类中是否包含指定名称对应的字段包括所有字段包括非public字段也包括父类和Object类的字段 * 查找指定类中是否包含指定名称对应的字段包括所有字段包括非public字段也包括父类和Object类的字段
* *
@ -195,8 +204,8 @@ public class ReflectUtil {
if (null == obj || null == field) { if (null == obj || null == field) {
return null; return null;
} }
field.setAccessible(true); setAccessible(field);
Object result = null; Object result;
try { try {
result = field.get(obj); result = field.get(obj);
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
@ -207,6 +216,7 @@ public class ReflectUtil {
/** /**
* 获取所有字段的值 * 获取所有字段的值
*
* @param obj bean对象 * @param obj bean对象
* @return 字段值数组 * @return 字段值数组
* @since 4.1.17 * @since 4.1.17
@ -253,14 +263,15 @@ public class ReflectUtil {
public static void setFieldValue(Object obj, Field field, Object value) throws UtilException { public static void setFieldValue(Object obj, Field field, Object value) throws UtilException {
Assert.notNull(obj); Assert.notNull(obj);
Assert.notNull(field, "Field in [{}] not exist !", obj.getClass().getName()); Assert.notNull(field, "Field in [{}] not exist !", obj.getClass().getName());
field.setAccessible(true);
if(null != value) { setAccessible(field);
if (null != value) {
Class<?> fieldType = field.getType(); Class<?> fieldType = field.getType();
if(false == fieldType.isAssignableFrom(value.getClass())) { if (false == fieldType.isAssignableFrom(value.getClass())) {
//对于类型不同的字段尝试转换转换失败则使用原对象类型 //对于类型不同的字段尝试转换转换失败则使用原对象类型
final Object targetValue = Convert.convert(fieldType, value); final Object targetValue = Convert.convert(fieldType, value);
if(null != targetValue) { if (null != targetValue) {
value = targetValue; value = targetValue;
} }
} }
@ -274,6 +285,7 @@ public class ReflectUtil {
} }
// --------------------------------------------------------------------------------------------------------- method // --------------------------------------------------------------------------------------------------------- method
/** /**
* 获得指定类本类及其父类中的Public方法名<br> * 获得指定类本类及其父类中的Public方法名<br>
* 去重重载的方法 * 去重重载的方法
@ -282,9 +294,9 @@ public class ReflectUtil {
* @return 方法名Set * @return 方法名Set
*/ */
public static Set<String> getPublicMethodNames(Class<?> clazz) { public static Set<String> getPublicMethodNames(Class<?> clazz) {
final HashSet<String> methodSet = new HashSet<String>(); final HashSet<String> methodSet = new HashSet<>();
final Method[] methodArray = getPublicMethods(clazz); final Method[] methodArray = getPublicMethods(clazz);
if(ArrayUtil.isNotEmpty(methodArray)) { if (ArrayUtil.isNotEmpty(methodArray)) {
for (Method method : methodArray) { for (Method method : methodArray) {
methodSet.add(method.getName()); methodSet.add(method.getName());
} }
@ -541,7 +553,7 @@ public class ReflectUtil {
* @throws SecurityException 安全异常 * @throws SecurityException 安全异常
*/ */
public static Set<String> getMethodNames(Class<?> clazz) throws SecurityException { public static Set<String> getMethodNames(Class<?> clazz) throws SecurityException {
final HashSet<String> methodSet = new HashSet<String>(); final HashSet<String> methodSet = new HashSet<>();
final Method[] methods = getMethods(clazz); final Method[] methods = getMethods(clazz);
for (Method method : methods) { for (Method method : methods) {
methodSet.add(method.getName()); methodSet.add(method.getName());
@ -643,6 +655,7 @@ public class ReflectUtil {
} }
// --------------------------------------------------------------------------------------------------------- newInstance // --------------------------------------------------------------------------------------------------------- newInstance
/** /**
* 实例化对象 * 实例化对象
* *
@ -682,7 +695,7 @@ public class ReflectUtil {
final Class<?>[] paramTypes = ClassUtil.getClasses(params); final Class<?>[] paramTypes = ClassUtil.getClasses(params);
final Constructor<T> constructor = getConstructor(clazz, paramTypes); final Constructor<T> constructor = getConstructor(clazz, paramTypes);
if (null == constructor) { if (null == constructor) {
throw new UtilException("No Constructor matched for parameter types: [{}]", new Object[] { paramTypes }); throw new UtilException("No Constructor matched for parameter types: [{}]", new Object[]{paramTypes});
} }
try { try {
return constructor.newInstance(params); return constructor.newInstance(params);
@ -714,18 +727,18 @@ public class ReflectUtil {
if (0 == parameterTypes.length) { if (0 == parameterTypes.length) {
continue; continue;
} }
constructor.setAccessible(true); setAccessible(constructor);
try { try {
return constructor.newInstance(ClassUtil.getDefaultValues(parameterTypes)); return constructor.newInstance(ClassUtil.getDefaultValues(parameterTypes));
} catch (Exception e) { } catch (Exception ignore) {
// 构造出错时继续尝试下一种构造方式 // 构造出错时继续尝试下一种构造方式
continue;
} }
} }
return null; return null;
} }
// --------------------------------------------------------------------------------------------------------- invoke // --------------------------------------------------------------------------------------------------------- invoke
/** /**
* 执行静态方法 * 执行静态方法
* *
@ -784,9 +797,7 @@ public class ReflectUtil {
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> T invoke(Object obj, Method method, Object... args) throws UtilException { public static <T> T invoke(Object obj, Method method, Object... args) throws UtilException {
if (false == method.isAccessible()) { setAccessible(method);
method.setAccessible(true);
}
try { try {
return (T) method.invoke(ClassUtil.isStatic(method) ? null : obj, args); return (T) method.invoke(ClassUtil.isStatic(method) ? null : obj, args);
@ -813,4 +824,18 @@ public class ReflectUtil {
} }
return invoke(obj, method, args); return invoke(obj, method, args);
} }
/**
* 设置方法为可访问私有方法可以被外部调用
*
* @param <T> AccessibleObject的子类比如ClassMethodField等
* @param accessibleObject 可设置访问权限的对象比如ClassMethodField等
* @since 4.6.8
*/
public static <T extends AccessibleObject> T setAccessible(T accessibleObject) {
if (null != accessibleObject && false == accessibleObject.isAccessible()) {
accessibleObject.setAccessible(true);
}
return accessibleObject;
}
} }