main 函数调用 : 通过代理者调用目标对象中的类 , 并在执行目标对象 Subject 的 request 方法时 , 对该方法进行逻辑增强 ;
① 方式一 :
public class Main { public static void main(String[] args) { // 1. 创建目标对象 Subject subject = new Subject(); // 2. 创建代理类 Proxy proxy = new Proxy(subject); // 3. 通过代理类调用目标对象的方法 proxy.request(); /* 代理类的作用 : 执行 目标对象 Subject 的 request 方法时 , 对该方法进行逻辑增强 ; */ } }
② 方式二 :
public class Main { public static void main(String[] args) { /* 下面的这种用法, 不需要关注目标对象 只需要了解 Proxy 代理者 调用者不了解目标对象的内部实现细节 目标对象也不了解调用者 */ AInterface aInterface = new Proxy(new Subject()); aInterface.request(); } }
执行结果 :
Proxy before Subject request Proxy after
2、动态代理示例
动态代理接口 :
/** * 代理者 需要实现的接口 * 该接口就是动态代理接口 */ public interface AInterface { void request(); }
目标对象 : 被代理的目标对象 , 需要实现代理接口 ;
public class Subject implements AInterface { @Override public void request() { System.out.println("Subject request"); } }
InvocationHandler 实现 : 这是 Hook 钩子 , 用于向被代理的目标对象的目标方法中注入业务逻辑 ;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class AInvocationHandler implements InvocationHandler { /** * 被代理的对象 */ Object target; public AInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before(); Object object = method.invoke(target, args); after(); return object; } /** * 被代理对象方法调用之前执行 */ private void before(){ System.out.println("AInvocationHandler before"); } /** * 被代理对象方法调用之后执行 */ private void after(){ System.out.println("AInvocationHandler after"); } }
动态代理执行 main 函数 :
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Main { public static void main(String[] args) { // 1. 创建目标对象 Subject subject = new Subject(); // 2. 获取目标对象类加载器 ClassLoader classLoader = subject.getClass().getClassLoader(); // 3. 获取接口 Class 数组, Subject 只实现了一个 AInterface 接口 Class<?>[] interfaces = subject.getClass().getInterfaces(); // 4. 创建 InvocationHandler , 传入被代理的目标对象 , 处理该目标对象中被代理的函数 InvocationHandler invocationHandler = new AInvocationHandler(subject); // 5. 动态代理 : // ① jdk 根据传入的参数信息 , 在内存中动态的创建 与 .class 字节码文件等同的字节码数据 // ② 将字节码数据 转为 对应的 字节码类型 // ③ 使用反射调用 newInstance 创建动态代理实例 AInterface proxy = (AInterface) Proxy.newProxyInstance( classLoader, interfaces, invocationHandler); // 正式调用被动态代理的类 proxy.request(); } }
执行结果 :
AInvocationHandler before Subject request AInvocationHandler after