目标:利用Proxy完成一个订单业务时间检测
知识点:
Proxy
- JDK动态代理:java.lang.reflect.Proxy。
- 动态生成代理类:在程序运行时生成代理类来进行代理,主要利用Java的反射机制。
- Proxy代理的是接口,并不是类或抽象类。
使用:
业务代码:
package com.miracle.study.aspect;
/**
* 订单业务接口
* @author Miracle
* @date 2021/4/4 12:52
*/
public interface IOrder {
/**
* 订单支付
* @throws InterruptedException
*/
void pay() throws InterruptedException;
/**
* 订单状态展示
*/
void show();
}
package com.miracle.study.aspect;
/**
* 订单业务接口实现
* @author Miracle
* @date 2021/4/4 12:53
*/
public class Order implements IOrder{
int state = 0;
@Override
public void pay() throws InterruptedException {
// 模拟业务进行
Thread.sleep(50);
this.state = 1;
}
@Override
public void show() {
System.out.println("order status:" + this.state);
}
}
Proxy切面接口:
package com.miracle.study.aspect;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 代理接口
* @author Miracle
* @date 2021/4/4 12:50
*/
public interface Aspect {
/**
* 方法执行前
*/
void before();
/**
* 方法执行后
*/
void after();
/**
* 代理类生成
* @param cls 需要代理的类
* @param aspects 所有切面实现类
* @param <T>
* @return
*/
static <T> T getProxy(Class<T> cls, String ... aspects) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
var aspectInsts = Arrays.stream(aspects).map(name -> {
try {
Class<?> clazz = Class.forName(name);
return (Aspect) clazz.getConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}).filter(Objects::nonNull).collect(Collectors.toList());
var inst = cls.getConstructor().newInstance();
return (T) Proxy.newProxyInstance(
cls.getClassLoader(),
cls.getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
for (var aspect : aspectInsts){
aspect.before();
}
var result = method.invoke(inst);
for (var aspect : aspectInsts){
aspect.after();
}
return result;
}
});
}
}
package com.miracle.study.aspect;
/**
* 切面实现类
* @author Miracle
* @date 2021/4/4 12:46
*/
public class TimeUsageAspect implements Aspect{
long start;
@Override
public void before() {
start = System.currentTimeMillis();
}
@Override
public void after() {
var usage = System.currentTimeMillis() - start;
System.out.format("time usage : %dms\n", usage);
}
}
测试:
package com.miracle.study.aspect;
import org.junit.jupiter.api.Test;
import java.lang.reflect.InvocationTargetException;
/**
* 测试
* @author Miracle
* @date 2021/4/4 17:42
*/
public class ProxyExampleTest {
@Test
public void test_proxy() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, InterruptedException {
IOrder order = Aspect.getProxy(Order.class, "com.miracle.study.aspect.TimeUsageAspect");
order.pay();
order.show();
}
}
参考资料
https://www.cnblogs.com/wobuchifanqie/p/9991342.html
https://blog.csdn.net/u012326462/article/details/81293186