关于JDK动态代理(代码级别)

代理

使用代理模式的作用:
功能增强:在你原有的功能上,增加了额外的功能。
控制访问:代理类不让你访问目标。例如商家不让用户访问厂家

实现代理的方式
静态代理:代理类是自己手工实现的,
自己创建一个java类表示代理类,同时所要的代理目标是确定的。
特点:实现简单;容易理解
缺点:目标类增加,代理类可能也要成倍增加;当接口中功能修改/增加,会影响众多实现类

动态代理:可以避免静态代理的缺点
在程序的执行过程中,使用jdk的反射机制,创建代理类对象,并动态指定要代理的目标类
也就是使用jdk的反射机制,创建对象的能力,创建的是代理类的对象,而不用手动创建
类文件。

JDK动态代理

什么是动态代理?
 使用jdk反射机制机制,创建对象的能力。创建的是代理类的对象,而不用你创建类文件,不用写java文件。
 jdk动态代理必须有接口,目标类必须实现接口;
 没有接口时,可以用cglib

动态代理能做什么?
 可以在不改变原来目标方法功能的前提下,可以在代理中增强自己的功能代码。
 
 例如A写了一个方法,B想去实现该方法的时候,发现该方法不完善,想要自己增强该方法,但是又不能访问其原码。于是可以用到动态代理,为该方法增强功能,既保证了原方法的完整,又不会修改其代码,符合了OCP开闭原则。

JDK动态代理的实现:
InvocationHandler接口:(执行的功能能代码)
 只有一个方法:invoke()表示代理对象要执行的功能代码(代理类要完成的功能写在该方法中)
 代理类完成的功能:用目标方法;功能增强
 怎么用:创建类实现接口InvocationHandler。
 重写invoke()方法,把原来静态代理中代理类要完成的功能写在方法中。

Method类:(执行的目标方法)
 表示方法的,就是目标类中的方法
 作用:通过Method可以执行某个目标类的方法,Method.invoke();
 怎么用:method.invoke(目标对象,“方法参数”);

Proxy类:(创建对象)
 核心的对象,创建代理对象。
 使用Proxy类的方法,代替new的使用。
 方法:静态方法 newProxyInstance()
 作用:创建代理类对象。
 
 public static Object new ProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
参数:
1.ClassLoader loader:类加载器,负责向内存中加载对象,使用反射机制获取对象的ClassLoader
类A,A.getClass(),getCloassLoader(),目标对象的类加载器
2.Class[] interfaces:接口,目标对象实现的接口,也是反射获取的。
3.InvocationHandler h:我们自己写的,代理类要完成的功能

实现动态代理的步骤

  1. 创建接口,定义目标类要完成的功能
  2. 创建目标类实现接口
  3. 创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
    调用目标方法
    增强功能
  4. 使用Proxy类的静态方法,创建代理对象。并把返回值转为接口类型

代码实例:

关于JDK动态代理(代码级别)_第1张图片
接口:

package service;

public interface UsbSell {
    float sell(int amount);
}

接口实现类:

package factory;

import service.UsbSell;

//目标类
public class UsbKingFactory implements UsbSell {
    @Override
    public float sell(int amount) {
        //目标方法
        System.out.println("目标类中,执行sell目标方法");
        return 85.0f;
    }
}

InvocationHandler接口的实现类:

package handler;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

//必须实现InvocationHandler接口,完成代理类要做的功能
//1.调用目标方法 2.功能增强
public class MySellHandler implements InvocationHandler {
    Object target=null;

    //动态代理的目标对象
    public MySellHandler(Object target) {
        //给目标对象赋值
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object res=null;
        res=method.invoke(target,args);
        if(res!=null){
            float price=(float)res;
            price=price+25;
            res=price;
        }
        return res;
    }
}

测试方法:

import factory.UsbKingFactory;
import handler.MySellHandler;
import service.UsbSell;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class MainShop {
    public static void main(String[] args) {
        //创建代理对象,使用Proxy
        //1.创建目标对象
        UsbSell factory=new UsbKingFactory();
        //2.创建InvocationHandler对象
        InvocationHandler handler =new MySellHandler(factory);
        //3.创建代理对象
        UsbSell proxy=(UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),
                factory.getClass().getInterfaces(),
                handler);
        //4.通过代理执行方法
        float price=proxy.sell(1);
        System.out.println("通过动态代理对象,调用方法:"+price);
    }
}

关于JDK动态代理(代码级别)_第2张图片

你可能感兴趣的:(关于JDK动态代理(代码级别))