代理模式之JDK动态代理

在这里插入图片描述

package com.bzyd.test.jdk_proxy_;

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

/**
 * @Description JDK动态代理示例
 * @Author dangxianyue
 * @Date 2022/9/25 1:05
 */
public class JdkDynamicProxyTest {

    public static void main(String[] args) {
        // 让代理对象的class文件写入到磁盘
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        Suitor suitor = new Suitor();//被代理者
        InvocationHandler h = new ProxyEnhancer(suitor);//增强器
        /**
         * 创建代理类实例,Proxy就是个空壳,需要指定一下三个参数,才能生成代理类实例
         * 第一个参数,ClassLoader loader,指定代理类的类加载器
         * 第二个参数:Class<?>[] interfaces,指定代理类要实现的接口列表
         * 第三个参数:InvocationHandler h,指定代理类的增强逻辑
         */
        Object _proxy = Proxy.newProxyInstance(suitor.getClass().getClassLoader(), suitor.getClass().getInterfaces(), h);
        System.out.println("_proxy: " + _proxy.getClass().getSuperclass().getName());
        //_proxy: java.lang.reflect.Proxy
        //从这里可以看出,JDK创建出来的代理类对象都继承了Proxy类,
        //实际上是,_proxy extends Proxy implements LoveLetter,但不是被代理者Suitor的子类,这是和Cglib代理的区别之一
        //而Java是单继承的,所以被代理者Suitor必须实现接口
        //@Aurowired
        //private xxxImpl xxx;
        //当用到代理类的场景时,这里用实现类接收会报错,得用接口去接收

        LoveLetter loveLetter = (LoveLetter) _proxy;
        loveLetter.sendLetter("小丽");//调用代理类对象

        //结果:
        //_proxy: java.lang.reflect.Proxy
        //增强逻辑【送情书】>>>>>>>>>>>>>开始
        //写情书:小丽,我喜欢你! (此处可以看出类内调用没有被代理增强)
        //送情书:小丽,这是有人送你的情书!
        //增强逻辑【送情书】>>>>>>>>>>>>>结束
    }
}

/**
 * 求爱接口
 */
interface LoveLetter {

    /**
     * 写情书
     *
     * @param name
     */
    void writeLetter(String name);

    /**
     * 送情书
     *
     * @param name
     */
    void sendLetter(String name);
}

/**
 * 追求者,被代理者
 * JDK代理是接口代理,被代理类必须实现某个接口
 */
class Suitor implements LoveLetter {

    @Override
    public void writeLetter(String name) {
        System.out.println("写情书:" + name + ",我喜欢你!");
    }

    @Override
    public void sendLetter(String name) {
        //注意,类内自调用,即,反射调用被代理者原逻辑,而原逻辑内又调用本类方法
        //相当于this.writeLetter(name),调用到的是被代理者的方法,而不是通过代理类调用到的增强方法
        //所以这就是为什么类内调用不被代理增强的原因
        //也就是@Transactional事务注解,在类内调用时无效的原因!!!
        writeLetter(name);
        System.out.println("送情书:" + name + ",这是有人送你的情书!");
    }

}


/**
 * 代理增强类
 * 封装增强逻辑
 * 必须实现java.lang.reflect.InvocationHandler接口
 */
class ProxyEnhancer implements InvocationHandler {

    /**
     * 被代理对象,反射调用方法要用到实例,所以得自己保存
     */
    private Suitor suitor;

    public ProxyEnhancer(Suitor suitor) {
        this.suitor = suitor;
    }

    /**
     * 增强逻辑
     * 底层原理是使用反射调用对象的方法
     * 效率比AspectJ预编译静态代理慢得多
     * 但不需要额外的编译,是在运行时动态生成代理增强类
     *
     * @param proxy  Proxy.newProxyInstance创建出来的代理类Proxy的一个实例
     * @param method 被代理对象suitor反射出来的被代理的方法
     * @param args   方法参数,反射调用要用到
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        String s = "writeLetter".equals(method.getName()) ? "写情书" :
                ("sendLetter".equals(method.getName()) ? "送情书" : "");
        System.out.println("增强逻辑【"+s+"】>>>>>>>>>>>>>开始");
        Object invoke = method.invoke(suitor, args);
        System.out.println("增强逻辑【"+s+"】>>>>>>>>>>>>>结束");
        return invoke;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alex·Guangzhou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值