动态代理
1、动态代理概述
动态代理中,代理类是在程序运行时利用反射机制动态创建的,使用JDK提供的Proxy类实现代理,这种代理方式被成为动态代理在实际开发过程中动态代理是通过JDK提供的Proxy类在程序运行时,运用反射机制动态创建而成
动态代理与静态代理的区别:静态代理需要自己写代理类、动态代理不用自己写代理类
虽然不需要自己定义代理类创建代理对象,但是要定义对被代理对象访问方法的拦截逻辑
代理类的作用,就是让被代理对象的某个方法执行之前或者执行之后加入其他增强逻辑(要在被代理对象的方法执行前进行拦截)
2、动态代理API
在java中实现动态代理,关键要使用到一个Proxy类和一个InvocationHandler接口
实例
Proxy类
java.lang.reflect.Proxy:是 Java 动态代理机制的主类(父类),它提供了用于创建动态代理类和实例的静态方法
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler handle)**解释说明:- 返回值: 该方法返回就是动态生成的代理对象- 参数列表说明:ClassLoader loader :定义代理类的类加载器Class<?>[] interfaces :代理类要实现的接口列表,要求与被代理类的接口一样InvocationHandler handle :就是具体实现代理逻辑的接口//参数的应用:ClassLoader loader //对象.getClass().getClassLoader()//目标对象通过getClass方法获取类的所有信息后,调用getClassLoader()方法来获取类加载器/*获取类加载器后,可以通过这个类型的加载器,在程序运行时,将生成的代理类加载到JVM即Java 虚拟机中,以便运行时需要*/Class<?>[] interfaces //对象.getClass().getInterfaces()//获取被代理类的所有接口信息,以便于生成的代理类可以具有代理类接口中的所有方法InvocationHandler//用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类方法的处理以及访问
InvocationHandler接口
java.lang.reflect.InvocationHandler是代理对象的实际处理代理逻辑的接口,具体代理逻辑在其 invoke 方法中实现
public Object invoke(Object proxy, Method method, Object[] args)**解释说明:- 返回值:方法被代理后执行的结果- 参数列表说明:Object proxy : 就是代理对象(通常不使用)Method method : 代理对象调用的方法Object[] args : 被代理方法中的参数 (因为参数个数不定,所以用一个对象数组来表示)如果方法不使用参数,则为 null//所有代理对象调用的方法,执行是都会经过invoke//因此如果要对某个方法进行代理增强,就可以在这个invoke方法中进行定义
3、动态代理实现
前置:
1、定义父接口
2、定义被代理类
实例:
//父接口(抽象角色)interface Star {double liveShow(double money);void sleep();}//被代理类:王宝强class BaoQiang implements Star {@Overridepublic double liveShow(double money) {System.out.println("宝强表演节目,赚了" + money + "元");return money;}@Overridepublic void sleep() {System.out.println("宝强累了,去睡觉了!!");}}
动态代理类生成:
public class Demo01 {public static void main(String[] args) {//创建被代理对象BaoQiang baoQiang = new BaoQiang();//创建代理对象//获取类加载器ClassLoader loader = baoQiang.getClass().getClassLoader();//获取被代理类的接口Class[] interfaces = baoQiang.getClass().getInterfaces();//Star//定义调用处理器(具体实现业务代理)InvocationHandler handler = new MyInvocationHandler(baoQiang);Object proxyObj = Proxy.newProxyInstance(loader, interfaces, handler);//proxyObj :即是Proxy的子类,也是Star的实现类Star starProxy = (Star) proxyObj;//多态double money = starProxy.liveShow(100);//这里一调用就会传入到invoke,invoke方法运行结束又会传回来System.out.println("money = " + money);starProxy.sleep();}}
定义代理逻辑:
//具体实现代理逻辑class MyInvocationHandler implements InvocationHandler {private BaoQiang baoQiang;public MyInvocationHandler(BaoQiang baoQiang) {this.baoQiang = baoQiang;}//代理对象调用的方法,都会经过这里@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//写代理逻辑String methodName = method.getName();System.out.println("调用的方法是:" + methodName + ",入参:" + Arrays.toString(args));//代理liveShowif (methodName.equals("liveShow")) {//前增强double m = (double) args[0];System.out.println("宋喆抽取佣金" + m * 0.8);Object result = method.invoke(baoQiang, m * 0.2);//后增强System.out.println("宋喆帮宝强存了" + result + "元到银行");return result;}//不写代理逻辑Object result = method.invoke(baoQiang, args);System.out.println("被代理调用结果" + result);return result;}}
