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

带你轻松搞懂JDK动态代理机制(ssm框架先行必备)

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

带你轻松搞懂JDK动态代理机制(ssm框架先行必备)

学习动态代理之前需要先搞清楚静态代理,可以回看我之前在Mybatis里写的代理那一篇文章

MyBatis入门基础3 ---代理

动态代理

使用反射机制,在程序执行过程中,创建代理类对象,无需创建类文件,代理的目标类是活动的,可以设计的。

动态代理需要的三个类

需要使用反射包 java.lang. reflect里面有三个类:

InvocationHandler(接口):表示代理要干什么(功能增强)

Method:表示目标类的方法

Proxy:创建代理对象

InvocationHandler接口

InvocationHandler是一个接口,在这个接口中只有一个invoke()方法,我们将代理类要完成的功能写在invoke()中,我们来看一下invoke()方法

Object invoke(Object proxy,Method method,0bject[] args)

invoke有三个参数

proxy:jdk创建的代理对象,无需赋值

method:目标类中的方法,也是jdk提供的

0bject[] args:目标类中方法的参数,jdk提供的

用法:首先创建一个类实现InvocationHandler接口,然后重写invoke(),我们将代理要完成的功能写在invoke()中,代理要实现的功能有两个:1.调用目标方法,2,完成对目标方法的增强

Method类

通过method可以执行某个目标类的方法。

  • method.invoke(目标对象,方法参数),这里的invoke和上述接口中的invoke碰巧同名而已。
Proxy类

我们通过调用Proxy里的静态方法newProxyInstance()创建代理对象,返回值就是代理对象

public static Obiect newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)

newProxyInstance方法依然是有三个参数

ClassLoader loader:目标对象的类加载器,通过反射获取

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

InvocationHandler h:我们自己写的代理类要完成的功能

实现动态代理的步骤:
  • 创建接口,定义目标类要完成的功能
  • 创建目标类实现接口
  • 创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
    1. 调用目标方法
    2. 增强功能
  • 使用Proxy类的静态方法,创建代理对象。并把返回值转为接口类型。(目标类一定是继承接口的,所以代理类对象可以返回接口类型)

我们来演示一下,我们以卖U盘为例,先看结构

厂家为目标类:定义U盘初始价格。商家为代理,首先获取厂家的初始价格,然后增加价格,我们以商店为测试,查看我们的购买价格是多少。

先定义目标接口:service.UserSell    这里我们定义了此次测试的主要功能:sell方法

package DynamicProxy.service;


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

定义目标类实现目标接口:factory.UsbFactory   厂家重写sell方法,定义出厂价为85元。

import DynamicProxy.service.UsbSell;


public class UsbFactory implements UsbSell {
    @Override
    
    public Integer sell(int amount) {
        System.out.println("目标类执行的sell目标方法");
        return 85;
    }
}

接下来实现带来要完成的功能:handler.SellHandler  ---- 增加价格

package DynamicProxy.handler;

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


public class SellHandler implements InvocationHandler {

    private Object target = null;

    
    public SellHandler(Object target) {
        //此时target就是目标对象
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object res = null;
        //proxy:目标对象;method:目标方法;args:目标方法的参数;
        //method.invoke(target,args); -----  调用目标方法
        res = method.invoke(target,args);


        //增强功能 :就是加个价格,目标方法卖85,代理完之后卖95
        if(res != null){
            Integer price = (Integer)res;
            price += 10;
            res = price;
        }
        System.out.println("目标方法被增强了");

        return res;
    }
}

最后在商店中进行测试:MainShop

package DynamicProxy;

import DynamicProxy.factory.UsbFactory;
import DynamicProxy.handler.SellHandler;
import DynamicProxy.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 UsbFactory();

        //2.创建InvocationHandler对象 -- 把factory传给SellHandler,相当于我们要给factory对象增强
        InvocationHandler handler = new SellHandler(factory);

        //3.创建代理对象,返回值是接口类型,目标对象实现了接口,所以可以转成接口类型
       UsbSell proxy = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),
                factory.getClass().getInterfaces (),handler);

        //4.测试:通过代理对象执行方法
        System.out.println("动态代理增强后的价格是:"+proxy.sell(1));

    }
}

查看结果

 我们发现,当我们以代理类调用sell方法时,目标方式执行了,代理增强的功能也执行了。

在静态代理中,一个代理类只能代理一个目标类,同时可能有多个代理类代理同一个目标类,当我们修改了目标类中的目标方法时,所有的代理类都会受到影响,需要重写目标方法。

而动态代理无需指定目标类,在上述案例中 实现代理增强功能时,我们以Object target来接收目标类。理论上我们可以接收无限多个目标类,当后续修改或是添加目标方法时,我们只需要在这里修改增强方法即可,减少了后期维护的成本。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/872530.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

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

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