设计模式【3.2】-- JDK动态代理源码分析有多香?

本文详细分析了JDK动态代理的实现原理,包括使用步骤和源码分析。通过示例展示了如何创建动态代理类,并探讨了为何JDK动态代理仅支持接口而非普通类。动态代理在Java中的应用广泛,如拦截器和切面编程,能有效降低代码耦合度。文章最后强调,动态代理结合反射和注解等技术,能实现更强大的功能。
摘要由CSDN通过智能技术生成

前面文章有说到代理模式:http://aphysia.cn/archives/dynamicagentdesignpattern

那么回顾一下,代理模式怎么来的?假设有个需求:

在系统中所有的 controller 类调用方法之前以及之后,打印一下日志。

假设原来的代码:

public class Person{
   
    public void method(){
   
        // 表示自己的业务逻辑
        process();
    }
}

如果在所有的类里面都添加打印方法,这样肯定是不现实的,如果我有几百个这样的类,写到崩溃,况且重复代码太多,冗余,还耦合到一块了,要是我下次不打日志了,做其他的,那几百个类又全部改一遍。

public class Person{
   
    public void method(){
   
        log();
        // 表示自己的业务逻辑
        process();
        log();
    }
}

静态代理

怎么样写比较优美呢?静态代理 这时候出场了,先把方法抽象成为接口:

public class IProxy(){
   
    public void method();
}

让具体的类去实现 IProxy,写自己的业务逻辑,比如:

public class Person implements IProxy(){
   
    public void method(){
   
        // 表示自己的业务逻辑
        process();
    }
}

然后弄个代理类,对方法进行增强:

public class PersonProxy implements IProxy{
   
    private IProxy target;
    public PersonProxy(IProxy target){
   
        this.target = target;
    }
    @Override
    public void method() {
   
        log();
        target.method();
        log();
    }
}

调用的时候,把真实的对象放到代理类的构造器里面,就可以得到一个代理类,对它的方法进行增强,好处就是,如果下次我要改,不打日志,做其他事情,我改代理类就可以了,不用到处改我的目标类的方法,而坏处还是很明显,要增强哪一个类,就要为它写一个代理类,这样好像不是很合理。

动态代理

怎么样能让他自动生成代理对象呢? 动态代理做的就是这个事情,它可以 动态 的根据我们提供的类,生成代理类的对象。

最主要的,是在运行时,动态生成,只要传入我们要代理增强的类相关的信息,比如类对象本身,类加载器,类的接口等,就可以生成,不用提前知道它是 A 类,B 类还是 C 类。

动态代理主要有三种实现方法,今天我们重点分析 JDK 动态代理:

  • JDK 代理:使用 JDK 提供的官方的 Proxy
  • 第三方 CGlib 代理:使用 CGLib 的 Enhancer 类创建代理对象
  • javassit:Javassist 是一个开源的分析、编辑和创建 Java 字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所创建的。

JDK 动态代理

使用步骤

  1. 新建一个接口
  2. 新建一个类,实现该接口
  3. 创建代理类,实现 java.lang.reflect.InvocationHandler 接口

代码如下:

IPlayDao.java(玩的接口)

public interface IPlayDao {
   
    void play();
}

StudentDao.java(实现了买东西,玩的接口的学生类)

public class StudentDao implements IPlayDao {
   
    @Override
    public void play() {
   
        System.out.println("我是学生,我想出去玩");
    }
}

MyProxy.java 代理类:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyProxy {
   
    private Object target;
    public MyProxy(Object target){
   
        this.target=target;
    }
    public Object getProxyInstance(){
   
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
   
                    // 一个接口可能很多方法,要是需要针对某一个方法,那么需要在函数里判断 method
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   
                        System.out.println(</
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值