ソースを参照

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点的修改
Golden Looly 6 年 前
コミット
5b5645cbbb

+ 8 - 2
hutool-aop/src/main/java/cn/hutool/aop/aspects/Aspect.java

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

+ 15 - 2
hutool-aop/src/main/java/cn/hutool/aop/aspects/SimpleAspect.java

@@ -8,23 +8,36 @@ import java.lang.reflect.Method;
  * 可以继承此类实现自己需要的方法即可
  * 
  * @author Looly
+ * @author ted.L
  *
  */
-public class SimpleAspect implements Aspect, Serializable{
+public abstract class SimpleAspect implements Aspect, Serializable{
 	private static final long serialVersionUID = 1L;
 
+    /**
+     * @see Aspect#before(Object, Method, Object[])
+     * @return 是否继续执行接下来的操作 默认值true
+     */
 	@Override
 	public boolean before(Object target, Method method, Object[] args) {
 		//继承此类后实现此方法
 		return true;
 	}
 
+    /**
+     * @see Aspect#after(Object, Method, Object[], Object)
+     * @return 是否允许返回值(接下来的操作) 默认值true
+     */
 	@Override
-	public boolean after(Object target, Method method, Object[] args) {
+	public boolean after(Object target, Method method, Object[] args, Object returnVal) {
 		//继承此类后实现此方法
 		return true;
 	}
 
+    /**
+     * @see Aspect#afterException(Object, Method, Object[], Throwable)
+     * @return 是否允许抛出异常 默认值true
+     */
 	@Override
 	public boolean afterException(Object target, Method method, Object[] args, Throwable e) {
 		//继承此类后实现此方法

+ 15 - 14
hutool-aop/src/main/java/cn/hutool/aop/aspects/TimeIntervalAspect.java

@@ -4,26 +4,27 @@ import java.lang.reflect.Method;
 
 import cn.hutool.core.date.TimeInterval;
 import cn.hutool.core.lang.Console;
+import cn.hutool.core.util.StrUtil;
 
 /**
  * 通过日志打印方法的执行时间的切面
  * @author Looly
  *
  */
-public class TimeIntervalAspect extends SimpleAspect{
-	private static final long serialVersionUID = 1L;
+public class TimeIntervalAspect extends SimpleAspect {
+    private static final long serialVersionUID = 1L;
 
-	private TimeInterval interval = new TimeInterval();
+    private TimeInterval      interval         = new TimeInterval();
 
-	@Override
-	public boolean before(Object target, Method method, Object[] args) {
-		interval.start();
-		return true;
-	}
-	
-	@Override
-	public boolean after(Object target, Method method, Object[] args) {
-		Console.log("Method [{}.{}] execute spend [{}]ms", target.getClass().getName(), method.getName(), interval.intervalMs());
-		return true;
-	}
+    @Override
+    public boolean before(Object target, Method method, Object[] args) {
+        interval.start();
+        return true;
+    }
+
+    @Override
+    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));
+        return true;
+    }
 }

+ 9 - 5
hutool-aop/src/main/java/cn/hutool/aop/interceptor/CglibInterceptor.java

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

+ 8 - 5
hutool-aop/src/main/java/cn/hutool/aop/interceptor/JdkInterceptor.java

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

+ 56 - 43
hutool-aop/src/test/java/cn/hutool/aop/test/AopTest.java

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