代理模式:我们需要做一件事情,又不期望自己亲力亲为,此时,可以找一个代理【中介】
我们【目标对象】与中介【代理对象】不能相互转换,因为是“兄弟”关系
需求:实现【加减乘除】计算器类
实现后发现问题如下
总结:在核心业务代码中,需要添加日志功能,但不期望在核心业务代码中书写日志代码。
实现方式
实现动态代理关键步骤
注意:代理对象与实现类【目标对象】是“兄弟”关系,不能相互转换
package com.atguigu.beforeaop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author Chunsheng Zhang 尚硅谷
* @create 2022/3/28 16:22
*/
public class MyProxy {
/**
* 目标对象【目标客户】
*/
private Object target;
public MyProxy(Object target){
this.target = target;
}
/**
* 获取目标对象的,代理对象
* @return
*/
public Object getProxyObject(){
Object proxyObj = null;
/**
类加载器【ClassLoader loader】,目标对象类加载器
目标对象实现接口:Class<?>[] interfaces,目标对象实现所有接口
InvocationHandler h
*/
ClassLoader classLoader = target.getClass().getClassLoader();
Class<?>[] interfaces = target.getClass().getInterfaces();
//创建代理对象
proxyObj = Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
//执行invoke()实现动态织入效果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//获取方法名【目标对象】
String methodName = method.getName();
//执行目标方法之前,添加日志
MyLogging.beforeMethod(methodName,args);
//触发目标对象目标方法
Object rs = method.invoke(target, args);
//执行目标方法之后,添加日志
MyLogging.afterMethod(methodName,rs);
return rs;
}
});
return proxyObj;
}
// class invocationImpl implements InvocationHandler{
// }
}
@Test
public void testBeforeAop(){
// int add = calc.add(1, 2);
// System.out.println("add = " + add);
//目标对象
Calc calc = new CalcImpl();
//代理工具类
MyProxy myProxy = new MyProxy(calc);
//获取代理对象
Calc calcProxy = (Calc)myProxy.getProxyObject();
//测试
// int add = calcProxy.add(1, 2);
int div = calcProxy.div(2, 1);
}