mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
clean history
This commit is contained in:
73
hutool-aop/src/main/java/cn/hutool/aop/ProxyUtil.java
Normal file
73
hutool-aop/src/main/java/cn/hutool/aop/ProxyUtil.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package cn.hutool.aop;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import cn.hutool.aop.aspects.Aspect;
|
||||
import cn.hutool.aop.proxy.ProxyFactory;
|
||||
import cn.hutool.core.util.ClassUtil;
|
||||
|
||||
/**
|
||||
* 代理工具类
|
||||
* @author Looly
|
||||
*
|
||||
*/
|
||||
public final class ProxyUtil {
|
||||
|
||||
/**
|
||||
* 使用切面代理对象
|
||||
*
|
||||
* @param <T> 切面对象类型
|
||||
* @param target 目标对象
|
||||
* @param aspectClass 切面对象类
|
||||
* @return 代理对象
|
||||
*/
|
||||
public static <T> T proxy(T target, Class<? extends Aspect> aspectClass){
|
||||
return ProxyFactory.createProxy(target, aspectClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用切面代理对象
|
||||
*
|
||||
* @param <T> 被代理对象类型
|
||||
* @param aspect 切面对象
|
||||
* @return 代理对象
|
||||
*/
|
||||
public static <T> T proxy(T target, Aspect aspect){
|
||||
return ProxyFactory.createProxy(target, aspect);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建动态代理对象<br>
|
||||
* 动态代理对象的创建原理是:<br>
|
||||
* 假设创建的代理对象名为 $Proxy0<br>
|
||||
* 1、根据传入的interfaces动态生成一个类,实现interfaces中的接口<br>
|
||||
* 2、通过传入的classloder将刚生成的类加载到jvm中。即将$Proxy0类load<br>
|
||||
* 3、调用$Proxy0的$Proxy0(InvocationHandler)构造函数 创建$Proxy0的对象,并且用interfaces参数遍历其所有接口的方法,这些实现方法的实现本质上是通过反射调用被代理对象的方法<br>
|
||||
* 4、将$Proxy0的实例返回给客户端。 <br>
|
||||
* 5、当调用代理类的相应方法时,相当于调用 {@link InvocationHandler#invoke(Object, java.lang.reflect.Method, Object[])} 方法
|
||||
*
|
||||
*
|
||||
* @param <T> 被代理对象类型
|
||||
* @param classloader 被代理类对应的ClassLoader
|
||||
* @param invocationHandler {@link InvocationHandler} ,被代理类通过实现此接口提供动态代理功能
|
||||
* @param interfaces 代理类中需要实现的被代理类的接口方法
|
||||
* @return 代理类
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T newProxyInstance(ClassLoader classloader, InvocationHandler invocationHandler, Class<?>... interfaces) {
|
||||
return (T) Proxy.newProxyInstance(classloader, interfaces, invocationHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建动态代理对象
|
||||
*
|
||||
* @param <T> 被代理对象类型
|
||||
* @param invocationHandler {@link InvocationHandler} ,被代理类通过实现此接口提供动态代理功能
|
||||
* @param interfaces 代理类中需要实现的被代理类的接口方法
|
||||
* @return 代理类
|
||||
*/
|
||||
public static <T> T newProxyInstance(InvocationHandler invocationHandler, Class<?>... interfaces) {
|
||||
return newProxyInstance(ClassUtil.getClassLoader(), invocationHandler, interfaces);
|
||||
}
|
||||
}
|
43
hutool-aop/src/main/java/cn/hutool/aop/aspects/Aspect.java
Normal file
43
hutool-aop/src/main/java/cn/hutool/aop/aspects/Aspect.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package cn.hutool.aop.aspects;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* 切面接口
|
||||
*
|
||||
* @author looly
|
||||
* @since 4.18
|
||||
*/
|
||||
public interface Aspect{
|
||||
|
||||
/**
|
||||
* 目标方法执行前的操作
|
||||
*
|
||||
* @param target 目标对象
|
||||
* @param method 目标方法
|
||||
* @param args 参数
|
||||
* @return 是否继续执行接下来的操作
|
||||
*/
|
||||
boolean before(Object target, Method method, Object[] args);
|
||||
|
||||
/**
|
||||
* 目标方法执行后的操作
|
||||
*
|
||||
* @param target 目标对象
|
||||
* @param method 目标方法
|
||||
* @param args 参数
|
||||
* @return 是否允许返回值(接下来的操作)
|
||||
*/
|
||||
boolean after(Object target, Method method, Object[] args);
|
||||
|
||||
/**
|
||||
* 目标方法抛出异常时的操作
|
||||
*
|
||||
* @param target 目标对象
|
||||
* @param method 目标方法
|
||||
* @param args 参数
|
||||
* @param e 异常
|
||||
* @return 是否允许抛出异常
|
||||
*/
|
||||
boolean afterException(Object target, Method method, Object[] args, Throwable e);
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
package cn.hutool.aop.aspects;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* 简单切面类,不做任何操作<br>
|
||||
* 可以继承此类实现自己需要的方法即可
|
||||
*
|
||||
* @author Looly
|
||||
*
|
||||
*/
|
||||
public class SimpleAspect implements Aspect, Serializable{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public boolean before(Object target, Method method, Object[] args) {
|
||||
//继承此类后实现此方法
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean after(Object target, Method method, Object[] args) {
|
||||
//继承此类后实现此方法
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean afterException(Object target, Method method, Object[] args, Throwable e) {
|
||||
//继承此类后实现此方法
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package cn.hutool.aop.aspects;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import cn.hutool.core.date.TimeInterval;
|
||||
import cn.hutool.core.lang.Console;
|
||||
|
||||
/**
|
||||
* 通过日志打印方法的执行时间的切面
|
||||
* @author Looly
|
||||
*
|
||||
*/
|
||||
public class TimeIntervalAspect extends SimpleAspect{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* 切面实现,提供一些基本的切面实现
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
package cn.hutool.aop.aspects;
|
@@ -0,0 +1,60 @@
|
||||
package cn.hutool.aop.interceptor;
|
||||
|
||||
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
|
||||
*
|
||||
*/
|
||||
public class CglibInterceptor implements MethodInterceptor, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Object target;
|
||||
private Aspect aspect;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param target 被代理对象
|
||||
* @param aspect 切面实现
|
||||
*/
|
||||
public CglibInterceptor(Object target, Aspect aspect) {
|
||||
this.target = target;
|
||||
this.aspect = aspect;
|
||||
}
|
||||
|
||||
public Object getTarget() {
|
||||
return this.target;
|
||||
}
|
||||
|
||||
@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) {
|
||||
aspect.afterException(target, method, args, ((InvocationTargetException) cause).getTargetException());
|
||||
} else {
|
||||
throw e;// 其它异常属于代理的异常,直接抛出
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aspect.after(target, method, args)) {
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
package cn.hutool.aop.interceptor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import cn.hutool.aop.aspects.Aspect;
|
||||
import cn.hutool.core.exceptions.UtilException;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
|
||||
/**
|
||||
* JDK实现的动态代理切面
|
||||
*
|
||||
* @author Looly
|
||||
*
|
||||
*/
|
||||
public class JdkInterceptor implements InvocationHandler, Serializable{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Object target;
|
||||
private Aspect aspect;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param target 被代理对象
|
||||
* @param aspect 切面实现
|
||||
*/
|
||||
public JdkInterceptor(Object target, Aspect aspect) {
|
||||
this.target = target;
|
||||
this.aspect = aspect;
|
||||
}
|
||||
|
||||
public Object getTarget() {
|
||||
return this.target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
final Object target = this.target;
|
||||
final Aspect aspect = this.aspect;
|
||||
Object result = null;
|
||||
if (aspect.before(target, method, args)) {
|
||||
try {
|
||||
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 (aspect.after(target, method, args)) {
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* 代理拦截器实现
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
package cn.hutool.aop.interceptor;
|
7
hutool-aop/src/main/java/cn/hutool/aop/package-info.java
Normal file
7
hutool-aop/src/main/java/cn/hutool/aop/package-info.java
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* JDK动态代理封装,提供非IOC下的切面支持
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
package cn.hutool.aop;
|
@@ -0,0 +1,25 @@
|
||||
package cn.hutool.aop.proxy;
|
||||
|
||||
import cn.hutool.aop.aspects.Aspect;
|
||||
import cn.hutool.aop.interceptor.CglibInterceptor;
|
||||
import net.sf.cglib.proxy.Enhancer;
|
||||
|
||||
/**
|
||||
* 基于Cglib的切面代理工厂
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
public class CglibProxyFactory extends ProxyFactory{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T proxy(T target, Aspect aspect) {
|
||||
final Enhancer enhancer = new Enhancer();
|
||||
enhancer.setSuperclass(target.getClass());
|
||||
enhancer.setCallback(new CglibInterceptor(target, aspect));
|
||||
return (T) enhancer.create();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package cn.hutool.aop.proxy;
|
||||
|
||||
import cn.hutool.aop.ProxyUtil;
|
||||
import cn.hutool.aop.aspects.Aspect;
|
||||
import cn.hutool.aop.interceptor.JdkInterceptor;
|
||||
|
||||
/**
|
||||
* JDK实现的切面代理
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
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());
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
package cn.hutool.aop.proxy;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import cn.hutool.aop.aspects.Aspect;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
|
||||
/**
|
||||
* 代理工厂<br>
|
||||
* 根据用户引入代理库的不同,产生不同的代理对象
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
public abstract class ProxyFactory implements Serializable{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 创建代理
|
||||
*
|
||||
* @param target 被代理对象
|
||||
* @param aspect 切面实现
|
||||
* @return 代理对象
|
||||
*/
|
||||
public abstract <T> T proxy(T target, Aspect aspect);
|
||||
|
||||
/**
|
||||
* 根据用户引入Cglib与否自动创建代理对象
|
||||
*
|
||||
* @param <T> 切面对象类型
|
||||
* @param target 目标对象
|
||||
* @param aspectClass 切面对象类
|
||||
* @return 代理对象
|
||||
*/
|
||||
public static <T> T createProxy(T target, Class<? extends Aspect> aspectClass){
|
||||
return createProxy(target, ReflectUtil.newInstance(aspectClass));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户引入Cglib与否自动创建代理对象
|
||||
*
|
||||
* @param <T> 切面对象类型
|
||||
* @param target 被代理对象
|
||||
* @param aspect 切面实现
|
||||
* @return 代理对象
|
||||
*/
|
||||
public static <T> T createProxy(T target, Aspect aspect) {
|
||||
return create().proxy(target, aspect);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户引入Cglib与否创建代理工厂
|
||||
*
|
||||
* @return 代理工厂
|
||||
*/
|
||||
public static ProxyFactory create() {
|
||||
try {
|
||||
return new CglibProxyFactory();
|
||||
} catch (NoClassDefFoundError e) {
|
||||
// ignore
|
||||
}
|
||||
return new JdkProxyFactory();
|
||||
}
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* 代理实现
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
package cn.hutool.aop.proxy;
|
60
hutool-aop/src/test/java/cn/hutool/aop/test/AopTest.java
Normal file
60
hutool-aop/src/test/java/cn/hutool/aop/test/AopTest.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package cn.hutool.aop.test;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import cn.hutool.aop.ProxyUtil;
|
||||
import cn.hutool.aop.aspects.TimeIntervalAspect;
|
||||
|
||||
/**
|
||||
* AOP模块单元测试
|
||||
*
|
||||
* @author Looly
|
||||
*
|
||||
*/
|
||||
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 "狗吃肉";
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user