clean history

This commit is contained in:
Looly
2019-08-14 10:02:32 +08:00
commit 6b011af032
1215 changed files with 159913 additions and 0 deletions

View 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);
}
}

View 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);
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,7 @@
/**
* 切面实现,提供一些基本的切面实现
*
* @author looly
*
*/
package cn.hutool.aop.aspects;

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,7 @@
/**
* 代理拦截器实现
*
* @author looly
*
*/
package cn.hutool.aop.interceptor;

View File

@@ -0,0 +1,7 @@
/**
* JDK动态代理封装提供非IOC下的切面支持
*
* @author looly
*
*/
package cn.hutool.aop;

View File

@@ -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();
}
}

View File

@@ -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());
}
}

View File

@@ -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();
}
}

View File

@@ -0,0 +1,7 @@
/**
* 代理实现
*
* @author looly
*
*/
package cn.hutool.aop.proxy;

View 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 "狗吃肉";
}
}
}