Merge pull request #561 from Ted-Engineer/v4-dev

1、切面after切点,将目标方法执行返回值,开放给切点 2、SimpleAspect没有直接使用的意义,应修改为抽象类 3、修改Aspect#afterException 没有使用返回值进行异常是否抛出的判断。 4、修改CglibInterceptor#intercept 和 JdkInterceptor#intercept 方法中 if else 为 if ,减少else判断,并支持 第3点的修改
This commit is contained in:
Golden Looly 2019-09-27 22:36:33 +08:00 committed by GitHub
commit 5b5645cbbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 106 additions and 66 deletions

View File

@ -6,6 +6,7 @@ import java.lang.reflect.Method;
* 切面接口 * 切面接口
* *
* @author looly * @author looly
* @author ted.L
* @since 4.18 * @since 4.18
*/ */
public interface Aspect{ public interface Aspect{
@ -22,13 +23,18 @@ public interface Aspect{
/** /**
* 目标方法执行后的操作 * 目标方法执行后的操作
* 如果 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 目标方法执行返回值
* @return 是否允许返回值接下来的操作 * @return 是否允许返回值接下来的操作
*/ */
boolean after(Object target, Method method, Object[] args); boolean after(Object target, Method method, Object[] args, Object returnVal);
/** /**
* 目标方法抛出异常时的操作 * 目标方法抛出异常时的操作

View File

@ -8,23 +8,36 @@ import java.lang.reflect.Method;
* 可以继承此类实现自己需要的方法即可 * 可以继承此类实现自己需要的方法即可
* *
* @author Looly * @author Looly
* @author ted.L
* *
*/ */
public class SimpleAspect implements Aspect, Serializable{ public abstract 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
*/
@Override @Override
public boolean after(Object target, Method method, Object[] args) { 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

@ -4,26 +4,27 @@ import java.lang.reflect.Method;
import cn.hutool.core.date.TimeInterval; import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.lang.Console; import cn.hutool.core.lang.Console;
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;
private TimeInterval interval = new TimeInterval(); private TimeInterval interval = new TimeInterval();
@Override @Override
public boolean before(Object target, Method method, Object[] args) { public boolean before(Object target, Method method, Object[] args) {
interval.start(); interval.start();
return true; return true;
} }
@Override @Override
public boolean after(Object target, Method method, Object[] args) { public boolean after(Object target, Method method, Object[] args, Object returnVal) {
Console.log("Method [{}.{}] execute spend [{}]ms", target.getClass().getName(), method.getName(), interval.intervalMs()); Console.log("Method [{}.{}] execute spend [{}]ms return value [{}]", target.getClass().getName(), method.getName(), interval.intervalMs(), StrUtil.toString(returnVal));
return true; return true;
} }
} }

View File

@ -13,6 +13,7 @@ import net.sf.cglib.proxy.MethodProxy;
* Cglib实现的动态代理切面 * Cglib实现的动态代理切面
* *
* @author looly * @author looly
* @author ted.L
* *
*/ */
public class CglibInterceptor implements MethodInterceptor, Serializable { public class CglibInterceptor implements MethodInterceptor, Serializable {
@ -45,14 +46,17 @@ public class CglibInterceptor implements MethodInterceptor, Serializable {
result = proxy.invokeSuper(obj, args); result = proxy.invokeSuper(obj, args);
} catch (UtilException e) { } catch (UtilException e) {
final Throwable cause = e.getCause(); final Throwable cause = e.getCause();
if (e.getCause() instanceof InvocationTargetException) { if (!(e.getCause() instanceof InvocationTargetException)) {
aspect.afterException(target, method, args, ((InvocationTargetException) cause).getTargetException()); // 其它异常属于代理的异常直接抛出
} else { throw e;
throw e;// 其它异常属于代理的异常直接抛出
} }
if(aspect.afterException(target, method, args, ((InvocationTargetException) cause).getTargetException())){
throw e;
}
} }
} }
if (aspect.after(target, method, args)) { if (aspect.after(target, method, args, result)) {
return result; return result;
} }
return null; return null;

View File

@ -13,6 +13,7 @@ import cn.hutool.core.util.ReflectUtil;
* JDK实现的动态代理切面 * JDK实现的动态代理切面
* *
* @author Looly * @author Looly
* @author ted.L
* *
*/ */
public class JdkInterceptor implements InvocationHandler, Serializable{ public class JdkInterceptor implements InvocationHandler, Serializable{
@ -46,14 +47,16 @@ public class JdkInterceptor implements InvocationHandler, Serializable{
result = ReflectUtil.invoke(target, method, args); result = ReflectUtil.invoke(target, method, args);
} catch (UtilException e) { } catch (UtilException e) {
final Throwable cause = e.getCause(); final Throwable cause = e.getCause();
if (e.getCause() instanceof InvocationTargetException) { if (!(e.getCause() instanceof InvocationTargetException)) {
aspect.afterException(target, method, args, ((InvocationTargetException) cause).getTargetException()); // 其它异常属于代理的异常直接抛出
} else { throw e;
throw e;// 其它异常属于代理的异常直接抛出 }
if(aspect.afterException(target, method, args, ((InvocationTargetException) cause).getTargetException())){
throw e;
} }
} }
} }
if (aspect.after(target, method, args)) { if (aspect.after(target, method, args, result)) {
return result; return result;
} }
return null; return null;

View File

@ -14,47 +14,60 @@ import cn.hutool.aop.aspects.TimeIntervalAspect;
*/ */
public class AopTest { public class AopTest {
@Test @Test
public void aopTest() { public void aopTest() {
Animal cat = ProxyUtil.proxy(new Cat(), TimeIntervalAspect.class); Animal cat = ProxyUtil.proxy(new Cat(), TimeIntervalAspect.class);
String result = cat.eat(); String result = cat.eat();
Assert.assertEquals("猫吃鱼", result); Assert.assertEquals("猫吃鱼", result);
} cat.seize();
}
@Test @Test
public void aopByCglibTest() { public void aopByCglibTest() {
Dog dog = ProxyUtil.proxy(new Dog(), TimeIntervalAspect.class); Dog dog = ProxyUtil.proxy(new Dog(), TimeIntervalAspect.class);
String result = dog.eat(); String result = dog.eat();
Assert.assertEquals("狗吃肉", result); Assert.assertEquals("狗吃肉", result);
} dog.seize();
}
static interface Animal { interface Animal {
String eat(); String eat();
}
/** void seize();
* 有接口 }
*
* @author looly
*
*/
static class Cat implements Animal {
@Override /**
public String eat() { * 有接口
return "猫吃鱼"; *
} * @author looly
} *
*/
static class Cat implements Animal {
/** @Override
* 无接口 public String eat() {
* return "猫吃鱼";
* @author looly }
*
*/ @Override
static class Dog { public void seize() {
public String eat() { System.out.println("抓了条鱼");
return "狗吃肉"; }
} }
}
/**
* 无接口
*
* @author looly
*
*/
static class Dog {
public String eat() {
return "狗吃肉";
}
public void seize() {
System.out.println("抓了只鸡");
}
}
} }