反射实现AOP

92 阅读1分钟
/**
 * @author xyf
 * @date 2021/7/7 10:16
 */
public interface Aspect {
void before();

void after();

/**
 * 代理实现
 *
 * @param cls     需要添加切面的类 主关注点
 * @param aspects  附加的切面程序, 需要继承 Aspect 类   附关注点
 * @param <T>
 * @return
 * @throws ClassNotFoundException
 */
static <T> T getProxy(Class<T> cls, String... aspects) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

	//获取 附关注点信息
	List<Try<Aspect>> aspectInets = Stream.of(aspects)
			// Try.ofFailable() 这个方法主要是做异常处理
			.map(name -> Try.ofFailable(() -> {
				// 获取附关注点的类
				Class clazz = Class.forName(name);
				// 获取Class 的构造函数 实例化 Class
		return (Aspect) clazz.getConstructor().newInstance();
	}))
			.filter(aspect -> aspect.isSuccess())
			.collect(Collectors.toList());

	// 实例化 Class T
	T clazz =  cls.getConstructor().newInstance();

	// 返回这个 T 的代理类  由这个 代理类来包装T
	return (T) Proxy.newProxyInstance(
			// 类加载器
			cls.getClassLoader(),
			// 这个 T 都实现了哪些接口
			cls.getInterfaces(),
			//代理调用这个 来调用 T的方法
			new InvocationHandler() {
				@Override
				public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
					// 调用这个接口的方法前 的方法
					for (Try<Aspect> aspectTry : aspectInets) {
						aspectTry.get().before();
					}
					//调用 T 的方法  clazz  代表队是 T  args 代表 T 可能的输入参数
					Object result = method.invoke(clazz, args);
					// 调用这个接口的方法后 的方法
					for (Try<Aspect> aspectTry : aspectInets) {
						aspectTry.get().after();
					}
					return result;
				}
			});




}

}

public interface IOrder {

void pay(String number,String number2) throws InterruptedException;

        void show();
}

public class Order implements IOrder {

int state = 0;

@Override
public void pay(String number,String number2) throws InterruptedException {
	Thread.sleep(50); // 模拟需要耗费时间
	this.state = 1;
	System.out.println("输入参数 1"+number);
	System.out.println("输入参数 1"+number2);
}

@Override
public void show() {

	System.out.println("order status:" + this.state);
}

}

  public class TEST {


@Test
public void testAop() throws InterruptedException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
	IOrder order ;

	order =Aspect.getProxy(Order.class, "AOP.proxy.TimeUsageAspect");
	order.pay("1111","2222");
	order.show();
}


}

public class TimeUsageAspect implements Aspect {

long start;

@Override
public void before() {
	start = System.currentTimeMillis();
}

@Override
public void after() {
	long usage = System.currentTimeMillis() - start;
	System.out.format("time usage : %dms\n", usage);

}


}