java动态代理

一、代理模式的作用

  • 功能增强: 基于某个功能,再增加一些功能。
    (比如目标类只负责核心功能,其他附属功能通过代理类完成。代理类的方法名与目标类的方法相同,内容不同,在核心功能外加了一些额外逻辑)
  • 控制访问: 防止直接访问目标。

在这里插入图片描述

代理类代理目标类
目标类是实现目标功能的类

二、实现代理的方式

  • 动态代理

    • 特点:
      • 在程序执行过程中,自动使用jdk反射机制创建代理对象(而不需要写.java源文件),并且动态指定要代理的目标类。
    • 优点:
    • 缺点
  • 静态代理

    • 特点:
      • 代理类是自己手动实现的。自己创建一个类作为代理类
      • 要代理的目标类是确定的。
    • 优点:
      • 实现简单,容易理解
      • 在不改变原目标对象代码的情况下,对目标的功能进行拓展
    • 缺点:
      • 当目标类增加了,代理类可能要成倍的增加,代理类过多
      • 当接口的功能增加或修改,会影响所有实现类,修改工作量大,不好管理维护 。

三、动态代理的实现

3.1 jdk动态代理

基于接口实现代理
使用java反射包中的接口和类实现动态代理,要求 代理类和工具类实现同一个接口
其中反射包是java.lang,reflect,里面有三个类:InvocationHandlerMethodProxy
① 创建目标接口

public interface Star{
	String sing(String name);
	void dance();
}

② 创建目标类实现目标接口

public class BigStar implements Star {
    private String name;

    public BigStar(String name) {
        this.name = name;
    }

    public String sing(String name) {
        System.out.println(this.name + "正在唱歌儿:" + name);
        return "谢谢儿!谢谢儿!";
    }

    public void dance() {
        System.out.println(this.name + "正在跳舞儿");
    }
}

③ 创建对应的处理器实现InvocationHandler接口,重写invoke方法(里面写增强业务)

public class StarInvocationHandler<T> implements java.lang.reflect.InvocationHandler {
    private final T target; // 存储目标对象

    public StarInvocationHandler(T target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(method.getName() + "方法执行前增强");
        Object result = method.invoke(target, args);
        System.out.println(method.getName() + "方法执行后增强");
        return result;
    }
}

④ 创建工厂类,为了简化创建代理对象的过程(这里用了泛型约束,可以不用)

public class ProxyHandlerFactory {
    /**
     * 创建 Star 接口的代理对象
     */
    public static <T extends Star> Star createStarProxy(T target) {
        return (Star) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new StarInvocationHandler<>(target));
    }

}

⑤ 测试调用

public class Main {
    public static void main(String[] args) {
        BigStar bigstar = new BigStar("迪丽热巴");
        Star starProxy = ProxyHandlerFactory.createStarProxy(bigstar);
        String result = starProxy.sing("老公老公我爱你");
        System.out.println(result);
    }
}

结果:
在这里插入图片描述

3.2 cglib动态代理

基于继承实现代理
cglib是一个第三方工具库,能够创建代理对象。
通过继承的方式实现动态代理,通过继承目标类,创建它的子类,在子类中重写父类的同名方法,实现功能的修改。(因为是继承重写的方式实现代理,因此要求目标类不能是final修饰,要重写的方法也不能是final修饰的)。

① 导入cglib依赖
② 创建目标类

public class BigStar {
    private String name;

    public BigStar() {}

    public BigStar(String name) {
        this.name = name;
    }

    public String sing(String name) {
        System.out.println(this.name + "正在唱歌儿:" + name);
        return "谢谢儿!谢谢儿!";
    }

    public void dance() {
        System.out.println(this.name + "正在跳舞儿");
    }
}

③ 创建拦截器

public class BigStarMethodInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println(method.getName() + "方法增强前");
        Object result = methodProxy.invokeSuper(o, objects); // 调用目标类方法
        System.out.println(method.getName() + "方法增强前");
        return result;
    }
}

④ 创建代理对象,测试

public class TestMain {
    @Test
    public void test() {
        // 创建与目标对象对应的拦截器
        BigStarMethodInterceptor bigStarMethodInterceptor = new BigStarMethodInterceptor();
        // 创建一个增强器对象
        Enhancer enhancer = new Enhancer();
        // 设置目标类
        enhancer.setSuperclass(BigStar.class);
        // 设置拦截处理器
        enhancer.setCallback(bigStarMethodInterceptor);
        // 创建代理对象(根据参数选择对应的 Constructor)
        BigStar bigStarProxy = (BigStar) enhancer.create(new Class[]{String.class}, new Object[]{"胖迪"});
        // 调用方法
        String s = bigStarProxy.sing("猪之歌");
        System.out.println(s);
    }
}

运行结果:
在这里插入图片描述

cglib的代理效率高于jdk代理。

如果想看看生成的代理对象长什么养,可以通过设置一个系统属性并指定路径,CgLib会把生成的代理对象写出到该位置:

	// CgLib提供的代理类生成器
	System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\idea_workspace\\ruoyi\\wipinfo_bigscreen_manager\\admin\\src");

在这里插入图片描述

参考资料:

  1. 哔哩哔哩 黑马程序员磊哥 【黑马磊哥】Java动态代理深入剖析,真正搞懂Java核心设计模式:代理设计模式
    https://www.bilibili.com/video/BV1ue411N7GX?share_source=copy_web
  2. 哔哩哔哩 动力节点 Java-JDK动态代理(AOP)使用及实现原理分析
    https://www.bilibili.com/video/BV1HZ4y1p7F1?share_source=copy_web
  3. 哔哩哔哩 上云_云哥 jdk动态代理,cglib动态代理,代理设计模式,aop切面编程
    https://www.bilibili.com/video/BV1tY411Z799?p=6&share_source=copy_web
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值