mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
enhance aop
This commit is contained in:
@@ -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);
|
||||
|
@@ -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) {
|
||||
//继承此类后实现此方法
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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());
|
||||
}
|
||||
}
|
||||
|
@@ -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("抓了只鸡");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user