JDK动态代理案例学习

文章介绍了JDK动态代理的原理,通过创建InvocationHandler实现动态调用目标类方法,并在调用前后添加额外的逻辑,如日志和事务管理。同时,通过一个生活中的电脑销售代理案例展示了动态代理如何在实际场景中应用,代理对象在调用方法时可以修改参数、增强返回值以及扩展功能。
摘要由CSDN通过智能技术生成

第一段原文链接:JDK动态代理案例_jdk动态代理实例_7Euro的博客-CSDN博客

原理


        JDK动态代理只提供接口的代理,不支持类的代理。核心InvocationHandler接口和Proxy类,
InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的代理对象。

代码实现

创建接口及实现类


public interface SomeService {
 
    void doSome();
 
    void doOther();
 

public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome() {
        System.out.println("doSome.......");
    }
 
    @Override
    public void doOther() {
        System.out.println("doOther.......");
    }

创建第三方增强方法


public class ServiceTools {
 
    public static void doLog() {
        System.out.println("添加日志");
    }
 
    public static void doTrans() {
        System.out.println("执行事务");
    }
 

创建InvocationHandler接口实现类

public class MyInvocationHandler implements InvocationHandler {
 
    private Object object;
 
    public MyInvocationHandler(Object object) {
        this.object = object;
    }
 
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("执行了MyInvocationHandler中的invoke方法");
        // 通过代理对象执行方法时,会调用执行这个invoke
        Object res = null;
        ServiceTools.doLog();
        // 执行目标类的方法,通过Method类实现
        res = method.invoke(object, args); // SomeServiceImpl.doSome;SomeServiceImpl.doOther;
        ServiceTools.doTrans();
        return res;
    }
}

编写测试类

public class MyApp {
 
    public static void main(String[] args) {
        SomeService service = new SomeServiceImpl();
        // 创建InvocationHandler对象
        InvocationHandler invocationHandler = new MyInvocationHandler(service);
        // 使用Proxy创建代理
        SomeService proxy = (SomeService) Proxy.newProxyInstance(service.getClass().getClassLoader(), service.getClass().getInterfaces(), invocationHandler);
        // 通过代理执行方法,会调用handler中的invoke()
        proxy.doSome();
    }
 
}

测试结果

执行了MyInvocationHandler中的invoke方法
添加日志
doSome.......
执行事务

第二段案例比较好原文链接:

代理模式--JDK动态代理案例_jdk动态代理实例_Java界的小白的博客-CSDN博客

JDK动态代理--生活代码案例

 通过以上生活案例,我们来写代码,总是代理模式和生活的意思一样,现在商业处处都是代理,买房子,微商等等,有了这些代理,客户获取了更好的感受。

1.卖电脑接口2

/**
 * 真实对象和代理对象实现相同的卖电脑接口
 */
public interface SaleComputer {
 
    String pay(double money);
 
    void show();
}

2.北京联想公司(真实对象)

public class Lenovo implements SaleComputer {
    @Override
    public String pay(double money) {
 
        System.out.println("客户支付了"+money+"买了一台电脑");
        return "联想电脑";
    }
 
    @Override
    public void show() {
        System.out.println("展示电脑");
    }
}

3.天津代理商(代理对象)

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
/**
 * 增强代理对象测试
 */
public class ProxyTest {
    public static void main(String[] args) {
 
        Lenovo lenovo = new Lenovo();
        /*
         *  java.lang.reflect.Proxy提供用于创建动态代理类和实例的静态方法,大家可以查看JDK文档。
         *  1.Proxy.newProxyInstance()通过调用newInstance 方法创建代理实例。
         *  2.方法中有三个参数
         *      ClassLoader loader:定义代理类的类加载器(即真实对象)
         *      Class<?>[] interfaces:真实对象实现的接口数组
         *      InvocationHandler h:调用处理程序,执行方法。
         */
 
        SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(),
                lenovo.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            //invoke方法是核心代理逻辑思想,代理对象调用的所有方法都会触发该方法执行
            //增强方式有三种:1.增强参数 2.增强返回值 3.增强方法体
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 
                /*
                 * 三个参数
                 *      1.proxy:就是代理对象本身
                 *      2.method:代理对象调用的方法,被封装为的对象。简单说 谁在运行调用,这个method就是谁。
                 *      3.args:代理对象调用方法时,传递的实际参数
                 */
 
 
                    //增强参数
                if (method.getName().equals("pay")) {
                    //增强参数,代理需要赚取利润,代理修改了参数。
                    //这里args[0]代表方法的第一个参数。
                    double money = (double) args[0];
                    money = money * 1.2;
                    //增强方法体
                    System.out.println("买电脑专车接送");
 
                    //修改了方法参数 这里method.invok就是调用方法。
                    String computer = (String) method.invoke(lenovo, money);
 
                    //增强方法体
                    System.out.println("买电脑免费配送");
 
                    //增强返回值
                    return computer+"送鼠标垫";
                } else {
                    //如果没有,那么就原样输出
                    Object obj = method.invoke(lenovo, args);
                    return obj;
                }
            }
        });
 
 
        String computer = proxy_lenovo.pay(5000);
        System.out.println(computer);
 
        proxy_lenovo.show();
    }
}

4.测试结果

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值