代理模式的理解,以及由此引发对设计模式的理解

2020-12-20  本文已影响0人  _小毛驴

在看狂神讲Spring AOP的时候,又顺便讲到了代理模式。

静态代理

静态代理模式还是比较好理解的。就是在客户服务商之间,架设一个中间商。原先的逻辑是:客户直接调用服务商。现在是:客户调用中间商,间接调用服务商。这样的改动,中间商赚了差价,但是,好处是中间商可以帮我们做一些额外的工作。

动态代理

如果这样去理解:JVM在运行期间动态生成代理类。所以,就叫动态代理,所以就好,那就差点意思了。
我们在这里从结果去理解动态代理,就容易不明就里。我们不妨从静态代理的问题开始推演。

package com.keqing.staticproxy;

public class ServiceProxy implements Service{
    
    private ServiceProvider serviceProvider;
    
    public  ServiceProxy(ServiceProvider serviceProvider) {
        this.serviceProvider = serviceProvider;
    }
    
    @Override
    public void add(Object obj) {
        System.out.println("日志-调用了方法:"+"add");
        serviceProvider.add(obj);
    }

    @Override
    public void delete(Integer id) {
        System.out.println("日志-调用了方法:"+"delete");
        serviceProvider.delete(id);
    }

    @Override
    public void update(Object obj) {
        System.out.println("日志-调用了方法:"+"update");
        serviceProvider.update(obj);
    }

    @Override
    public void query() {
        System.out.println("日志-调用了方法:"+"query");
        serviceProvider.query();
    }

}

经过上面的分析。问题就水落石出了。

静态代理面临的问题:我们需要在中间商调用服务商这个过程中,切入一个拦截器方法,处理通用业务逻辑

jdk给我们提供了一整套方案。这套方案是这样的。

public class ServiceProxy implements InvocationHandler{
    private Service service;
    public ServiceProxy(Service service) {
        this.service = service;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("此处打印日志。。。。。");
        return method.invoke(service, args);
    }
}
Service serviceProvider = new ServiceProvider();
ServiceProxy serviceProxy = new ServiceProxy(serviceProvider);
//jdk的动态代理,实现动态创建代理类。
Object proxyObj = Proxy.newProxyInstance(
                serviceProvider.getClass().getClassLoader(),
                serviceProvider.getClass().getInterfaces(), 
                serviceProxy
                );
Service proxy = (Service)proxyObj;
proxy.query();

jdk通过我们传入的接口拦截器 这两个参数,就动态创建出来了我们需要的中间商。与静态代理相比。我们少了自己创建中间商这一步,这还不是最关键的。这只是我们解决问题路上的一个附带结果,我们不是真的为了省略中间商而来,回头看,我们为啥要改造静态代理。我们需要切入一个实现通用业务逻辑的拦截器,然而这个拦截器的切入又需要改造中间商。改造之后的中间商又是高度抽象化的,可以由jdk来代劳。
所以,最终,我们解决了我们的问题,也砍掉了中间商
我想再说一下,jdk生成的动态代理类,这个类,如果我们去看jdk源码的话,底层是要用到字节码的技术,动态的先按照固定模板拼凑出来实现了接口的代理类,然后,编译为class文件,加载到内存中。了解到这一步,我们自然而然的就想到了,我们可以动态的拼凑一个继承了服务商的代理类。这里根本就没有要让服务商去继承的任何动机,就不会违反java单继承的原则。所以,我才说,jdk动态代理实现必须拥有接口,是方案选择的不同而已,是面向接口编程思想的体现而已。根本不是某些人说的java是单继承多实现造成的。cglib库的存在也很好的说明了这个问题。

总结

上面的代理模式,我们作为开发者需要做什么工作,我们处于什么位置。如果在学习设计模式的过程中,我们很容易昏了头。往往感觉很多设计模式都是雷同的。
所以,我慢慢感觉到,在学习涉及模式的时候,我们在利用这个设计模式的时候,是处于怎样的一个位置,我们需要做哪些开发工作。
就拿代理模式来说

上一篇 下一篇

猜你喜欢

热点阅读