栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

详解JDK动态代理使用及原理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

详解JDK动态代理使用及原理

文章目录
  • 一.代理模式
  • 二.使用代理模式的作用
  • 三.实现代理的方式
    • 1.静态代理
      • (1)特点
      • (2)举例(用户购买商品的行为)
      • (3)缺点
    • 2.动态代理
      • (1)特点
      • (2)实现
        • jdk动态代理
        • a. InvocationHandler接口(调用处理器)
        • b. Method类
        • c. Proxy类
        • d.实现步骤

一.代理模式

为其他对象提供一种代理以控制对这个对象的访问。有些情况下,一个对象不适合或者不能引用另一个对象,而代理对象可以在客户类和目标对象之前起到中介的作用。

二.使用代理模式的作用
  1. 功能增强:在不改变目标方法的前提下,通过代理增加额外的功能。
  2. 控制访问:代理类不让你直接访问目标
三.实现代理的方式 1.静态代理 (1)特点

a.代理是你手工实现的,自己创建一个Java类,代表代理类
b.你要代理的目标类是明确的
c.实现简单,容易理解

(2)举例(用户购买商品的行为)

用户:客户端类
商家:代理,代理某个商品
厂家:目标类

实现步骤:
a.创建一个接口,定义卖东西的行为
b.创建厂家类,实现步骤a中的接口
c.创建商家类,也就是代理,实现步骤a中的接口
d.创建用户类,调用商家类的方法购买东西

代理类实现的功能:
a.调用目标类的方法
b.功能增强

(3)缺点

当项目中目标类和和代理类很多的时候
a.当目标类增加时,代理类可能要成倍的增加
b.当接口中功能增加或修改时,会影响众多的代理类和目标类

2.动态代理 (1)特点

在程序运行过程中,通过jdk的反射机制,创建代理类对象,并动态的指定其目标类。
即就是一种创建java对象的能力,让你不用手动去创建代理类。

(2)实现 jdk动态代理

使用Java反射包中的类和接口实现动态代理
java.lang.reflect中有三个类/接口:InvocationHandler,Method,Proxy

a. InvocationHandler接口(调用处理器)

其中只有一个方法:invoke() :代理对象要执行的功能代码
方法原型:
public object invoke(object proxy,Method method,Object args)
参数:
object proxy : jdk创建的代理对象
Method method:目标类中的方法,是jdk提供method对象的
Object[] args:目标类中方法的参数,jdk提供的
使用:
(1)创建类实现InvocationHandler接口
(2)重写invoke()方法,将代理类要实现的功能写入invoke()中

b. Method类

作用:执行某个目标类的方法

method.invoke(目标对象,方法的参数);
method.invole(service,"张三");
c. Proxy类

作用:创建代理对象
方法:静态方法public static Object newProxyInstance()

//方法原型
//该方法返回值就是代理对象
    public static Object newProxyInstance(ClassLoader loader,
                                          Class[] interfaces,
                                          InvocationHandler h)

参数说明:

ClassLoader loader:
类加载器,向内存中加载对象,通过反射机制获取对象的ClassLoader,是目标对象的类加载器。

//a类
a.getClass().getClassLoader();

Class[] interfaces:
接口,目标对象实现的接口,也是反射获取的

InvocationHandler h:
是我们自己写的代理类要实现的功能

d.实现步骤

1.创建接口,定义目标类要实现的功能

package com.xhy.service;

//目标接口
//售卖u盘的功能
public interface usbSell {
    float sell(int amount);
}

2.创建目标类实现接口

package com.xhy.factory;

import com.xhy.service.usbSell;

//目标类
//u盘厂家实现卖u盘的功能
public class usbkingFactory implements usbSell {
    @Override
    //目标方法
    //amount是购买数量
    public float sell(int amount) {
        System.out.println("目标类执行了sell目标方法!");
        
        return 65.0f; //u盘的厂家价格
    }
}

3.创建InvocationHandler的实现类,在invoke方法中实现代理对象的功能

package com.xhy.handler;

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

//实现InvocationHandler接口,完成代理类的功能
//1.实现目标方法
//2.功能增强
public class mysellHandler implements InvocationHandler {

    private 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;

        //1.执行目标方法
        //向厂家发送订单,厂家发货
        res = method.invoke(target,args); //厂家的价格

        //2.功能增强
        //商家(代理)需要加价,并且赠送买家优惠券
        if (res !=null){
            Float price = (Float) res;
            price = price +30;
            res = price;
        }

        System.out.println("商家赠送了一张五元优惠券");

        //商家加价后的新价格
        return res;

    }
}

4.使用Proxy类的静态方法,创建代理对象,并把返回值转为接口类型

import com.xhy.factory.usbkingFactory;
import com.xhy.handler.mysellHandler;
import com.xhy.service.usbSell;

import java.lang.reflect.Proxy;

public class mainShop {
    public static void main(String[] args) {
        //创建代理对象,使用Proxy
        //1.创建目标类对象
        usbkingFactory factory = new usbkingFactory();

        //2.创建InvocationHandler对象
        mysellHandler 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);
    }
}
//呼,好累啊好累啊

5.执行结果

目标类执行了sell目标方法!
商家赠送了一张五元优惠券
通过代理对象调用了目标方法(商家向厂家发送了订单):95.0
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/355951.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号