Java学习:动态代理的一点小理解

Posted _acct

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java学习:动态代理的一点小理解相关的知识,希望对你有一定的参考价值。

手动实现

之前的一篇讲IoC的博文提到了代理模式,事实上代理模式就是AOP实现的重要基石。但是上面的代码有一个显而易见的缺陷,也就是之前讲解反射内容时提到的:不具备动态性

上面代码中的Server就像是反射理解博文中提到的工厂订单管理员一样,每增加一样菜系,就需要相应更新手上的菜单。类比反射特性,我们完全可以做到让服务员不需要手上拿着菜单来为顾客服务:

// 服务员实现类
public class ServerImpl implements Server {

    // 采用组合的方式引入noodles
    private Noodles noodles;

    @Override
    public void getNoodles() {
        // 代理模式
        noodles.getNoodles();
    }

    // 利用反射特性
    @Override
    public void setNoodles(String noodles) {
        this.noodles = (Noodles) Class.forName(noodles).newInstance();
        }
    }
}

API实现

之前的动态代理是我们手动实现的,JDK其实自带了很多实现动态代理的类和方法。可能初次接触时会显得有些复杂,所以先画一张图来表示我们整个的设计思路:

技术图片

之前在讨论IoC举的餐馆用例中,除了不具备动态性之外还有一个缺陷:服务员只服务于本餐馆,也就是说,我们能不能把服务员这个群体抽离出来,不仅服务这个餐馆,也能服务于多家餐馆,以实现代码的复用呢?

现实生活中有一种类型的公司,叫做家政公司,我们可以类比来编写一个服务员工厂:

public class ServerFactory implements InvocationHandler {
    
    private Object target;
    // 设定服务对象
    public void setTarget(Object target) {
        this.target = target;
    }

    // 返回具体的服务团队
    public Object getServer() {
        return Proxy.newProxyInstance(
                this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }
    
    @Override
    // 这一部分代码暂时忽略不管
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(target, args);
    }
}

这是利用java.lang.reflect包提供的动态代理相关类和方法编写的ServerFactory。最后的invoke方法是继承接口要求的重写方法,不妨碍我们理解,暂时忽略,主要关注前半部分的代码。

前半部分代码非常好理解:

  1. 工厂接到业务需求:给某某提供服务。派出服务团队
  2. 利用setTarget确定服务对象。
  3. 使用getServer返回对应的服务人员。

下面使用这个类进行测试,同样以与餐馆厨师对接为例:

public class ServerTest {
    public static void main(String[] args) {
        // 获取服务员团队
        ServerFactory serverGroup = new ServerFactory();
        // 设定该团队对接面食厨师
        serverGroup.setCooker(new NoodleCooker());
        // 获取单个服务员
        Cooker server = (Cooker) serverGroup.getServer();
        // 顾客点餐
        server.cooking();
    }
}

// NoodleCooker类
public class NoodleCooker implements Cooker {

    @Override
    public void cooking() {
        System.out.println("开始下面了!");
    }
}

// Cooker接口
public interface Cooker {
    void cooking();
}

我们实现了服务员和餐馆之间的解耦。有了服务员工厂,可以给任意的客户提供专业服务团队(setTarget),并且为每一次服务需求提供单个服务员进行实现(getServer)。

以上是关于Java学习:动态代理的一点小理解的主要内容,如果未能解决你的问题,请参考以下文章

柯里化的一点小理解

Layui的一点小理解(上)

主仆模式的一点小理解

关于Java动态代理的一点想法

那些老师没讲的东西——关于指针与数组的一点小用法

那些老师没讲的东西——关于指针与数组的一点小用法