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

@@ -4,19 +4,19 @@ import java.lang.reflect.Method;
/**
* 切面接口
*
*
* @author looly
* @author ted.L
* @since 4.18
*/
public interface Aspect{
public interface Aspect {
/**
* 目标方法执行前的操作
*
*
* @param target 目标对象
* @param method 目标方法
* @param args 参数
* @param args 参数
* @return 是否继续执行接下来的操作
*/
boolean before(Object target, Method method, Object[] args);
@@ -24,25 +24,25 @@ public interface Aspect{
/**
* 目标方法执行后的操作
* 如果 target.method 抛出异常且
*
* @param target 目标对象
* @param method 目标方法
* @param args 参数
* @param returnVal 目标方法执行返回值
* @return 是否允许返回值(接下来的操作)
* @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, Object returnVal);
/**
* 目标方法抛出异常时的操作
*
*
* @param target 目标对象
* @param method 目标方法
* @param args 参数
* @param e 异常
* @param args 参数
* @param e 异常
* @return 是否允许抛出异常
*/
boolean afterException(Object target, Method method, Object[] args, Throwable e);

View File

@@ -6,38 +6,42 @@ import java.lang.reflect.Method;
/**
* 简单切面类,不做任何操作<br>
* 可以继承此类实现自己需要的方法即可
*
* @author Looly
* @author ted.L
*
* @author Looly, ted.L
*/
public abstract class SimpleAspect implements Aspect, Serializable{
public 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
*/
/**
* 目标方法执行后的操作
* 如果 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
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) {
//继承此类后实现此方法

View File

@@ -8,23 +8,27 @@ import cn.hutool.core.util.StrUtil;
/**
* 通过日志打印方法的执行时间的切面
* @author Looly
*
* @author Looly
*/
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
public boolean before(Object target, Method method, Object[] args) {
interval.start();
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;
}
@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(), //
returnVal);
return true;
}
}

View File

@@ -1,30 +1,27 @@
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.lang.reflect.InvocationTargetException;
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实现的动态代理切面
*
* @author looly
* @author ted.L
*
* @author looly, ted.L
*/
public class CglibInterceptor implements MethodInterceptor, Serializable {
private static final long serialVersionUID = 1L;
private Object target;
private Aspect aspect;
/**
* 构造
*
*
* @param target 被代理对象
* @param aspect 切面实现
*/
@@ -40,22 +37,20 @@ public class CglibInterceptor implements MethodInterceptor, Serializable {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object result = null;
// 开始前回调
if (aspect.before(target, method, args)) {
try {
// result = ReflectUtil.invoke(target, method, args);
result = proxy.invokeSuper(obj, args);
} catch (UtilException e) {
final Throwable cause = e.getCause();
if (!(e.getCause() instanceof InvocationTargetException)) {
// 其它异常属于代理的异常,直接抛出
} catch (InvocationTargetException e) {
// 异常回调(只捕获业务代码导致的异常,而非反射导致的异常)
if (aspect.afterException(target, method, args, e.getTargetException())) {
throw e;
}
if(aspect.afterException(target, method, args, ((InvocationTargetException) cause).getTargetException())){
throw e;
}
}
}
// 结束执行回调
if (aspect.after(target, method, args, result)) {
return result;
}

View File

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

View File

@@ -6,16 +6,18 @@ import cn.hutool.aop.interceptor.JdkInterceptor;
/**
* JDK实现的切面代理
*
* @author looly
*
* @author looly
*/
public class JdkProxyFactory extends ProxyFactory{
public class JdkProxyFactory extends ProxyFactory {
private static final long serialVersionUID = 1L;
@Override
@SuppressWarnings("unchecked")
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;
import cn.hutool.core.lang.Console;
import org.junit.Assert;
import org.junit.Test;
@@ -8,66 +9,63 @@ import cn.hutool.aop.aspects.TimeIntervalAspect;
/**
* AOP模块单元测试
*
* @author Looly
*
* @author Looly
*/
public class AopTest {
@Test
public void aopTest() {
Animal cat = ProxyUtil.proxy(new Cat(), TimeIntervalAspect.class);
String result = cat.eat();
Assert.assertEquals("猫吃鱼", result);
cat.seize();
}
@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);
@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();
interface Animal {
String eat();
void seize();
}
void seize();
}
/**
* 有接口
*
* @author looly
*
*/
static class Cat implements Animal {
/**
* 有接口
*
* @author looly
*/
static class Cat implements Animal {
@Override
public String eat() {
return "猫吃鱼";
}
@Override
public String eat() {
return "猫吃鱼";
}
@Override
public void seize() {
System.out.println("抓了条鱼");
}
}
@Override
public void seize() {
Console.log("抓了条鱼");
}
}
/**
* 无接口
*
* @author looly
*
*/
static class Dog {
public String eat() {
return "狗吃肉";
}
/**
* 无接口
*
* @author looly
*/
static class Dog {
public String eat() {
return "狗吃肉";
}
public void seize() {
System.out.println("抓了只鸡");
}
}
public void seize() {
Console.log("抓了只鸡");
}
}
}