动态代理
理解这个问题之前 我们先来复习一下通过反射怎么
调用
运行时类的指定的方法
先来一个Person类
package com.zyk;
public class Person {
private int id;
private String name;
private String show(String nation){
System.out.println("我的国籍是"+nation);
return nation;
}
}
我们来看怎么调用
package com.zyk;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectTest {
public static void main(String[] args) throws Exception {
//获取Class实例
Class clazz=Person.class;
//创建运行时类的对象
Object o = clazz.newInstance();
//获取指定的某个方法
//参数1 获取的方法的名称
//参数2 获取方法的形参列表
Method show = clazz.getDeclaredMethod("show", String.class);
//保证当前方法可以访问
show.setAccessible(true);
//去执行该运行时类的方法 就是执行Person的show方法
//参数一 该方法的调用者 参数2 给方法形参赋值的实参
//invoke方法的返回值就是对应类中调用方法的返回值
Object returnValue=show.invoke(o,"china");
System.out.println(returnValue);
}
}
结果
我的国籍是china
china
下面我们来看动态代理
这里 我们要把握一个核心 (自己总结的)
调用代理类的方法 就是在代理类的方法中调用被代理类的同名方法
始终把这句话贯穿理解 我相信可以理解清楚动态代理
(说一个小插曲 你是不是想到了动态规划呢? 哈哈 都是劝退我们的东西 但我们要坚持下去 才会有收获啊)
我们来看一下动态代理要解决的两个核心问题
如何根据被代理对象 动态的生成一个代理类对象
2)
当我们通过代理类对象调用方法a时 如何动态的去调取被代理类中的同名方法a
package test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//接口
interface Human{
String getBelief();
void eat(String food);
}
//被代理类
class SuperMan implements Human{
@Override
public String getBelief() {
return "I believe I can fly";
}
@Override
public void eat(String food) {
System.out.println("我喜欢吃"+food);
}
}
//代理类
class ProxyFactory {
//此方法 返回一个代理类对象
public static Object getProxyInstance(Object object){//object被代理类对象
MyInvocationHandler myInvocationHandler=new MyInvocationHandler();
myInvocationHandler.bind(object);
//第一个参数 object.getClass().getClassLoader() 该被代理对象的类加载器
//第二个参数 object.getClass().getInterfaces() 被代理对象实现的接口数组
//也就是被代理对象实现了那些接口 因为我们的代理对象和被代理对象要实现同一个接口
//所以第二个参数要拿到 被代理对象实现了哪些接口
//第三个参数 MyInvocationHandler的对象
//这个方法动态的创建了一个代理类对象
return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),myInvocationHandler);
}
}
class MyInvocationHandler implements InvocationHandler{
private Object object;//需要使用被代理类的对象进行赋值
public void bind(Object object){
this.object=object;
}
//当我们通过代理类的对象 调用方法a时 就会自动调用下面的invoke()方法
//我们这个MyInvocationHandler类的对象作为了newProxyInstance这个方法的第三个参数
//当执行到newProxyInstance这个方法是 就会自动进入我们这个invoke方法
//所以我们将被代理类要执行的方法a声明在invoke()中
//该方法的第一个参数 Object proxy 我们创建的代理类对象newProxyInstance
//method 就是代理类对象要调用的那个方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//被代理类去调用同名方法 注意第一个参数是object
//也就是说这里利用反射调用了被代理类的指定方法
Object returnValue=method.invoke(object,args);
return returnValue;
}
}
public class ProxyTest {
public static void main(String[] args) {
SuperMan superMan=new SuperMan();
//创建代理类对象
Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
proxyInstance.eat("麻辣烫");
String belief=proxyInstance.getBelief();
System.out.println(belief);
}
}
结果
我喜欢吃麻辣烫
I believe I can fly
最后 希望大家不管生活有多难 我们都要勇敢的面对他 坚持下去 我们共勉!