JAVA中基于JDK的静态代理和动态代理

JAVA中基于JDK的静态代理和动态代理

1. 什么是代理

代理在我们生活中也就是所谓的中介。那么为什么我们需要中介呢?

举个例子来说:
我现在想买二手房,但是要面临很多问题。比如找房源,房子质量测评,房子过户合同要如何编写等一系列繁琐的事情。这个时候就需要中介出场了,他们可以帮我们把其他需要事前和事后处理的事情都帮我们做了。

2. 代理的功能

1.只要关注接口本身的功能而不用过多关注具体如何实现。具体的实现由代理类来进行操作。

2.遵循开闭原则,在不修改需求的情况下可以增加很多的功能。

3. 如何实现

代理的实现方式有很多,在JAVA中具体的代理类型有两种,分别是静态代理和动态代理。它的实现方式也有两种,分别是基于JDK和基于cglib的方式,想要知道它们的具体区别请直接跳到第4章节,本篇我们就来讲讲基于JDK的方式实现。下面我们来聊聊他们是如何实现的。

3.1 静态代理

顾名思义这个是我们在代码运行前就实现了。直接通过程序员硬编码书写出来的。

代理接口

//我的想法是要买房子
public interface MyIdea {
    void buyHouse();
}

委托类,处理具体业务

public class MyIdeaimpl implements MyIdea{
    @Override
    public void buyHouse() {
        System.out.println("我想买房子");
    }
}

代理的实现类

public class MyIdeaProxy implements MyIdea{
    MyIdeaimpl myIdeaimpl;

    public MyIdeaProxy(MyIdeaimpl myIdeaimpl){
        this.myIdeaimpl=myIdeaimpl;
    }

    @Override
    public void buyHouse() {
        searchHouse();
        myIdeaimpl.buyHouse();
        dealDoc();
    }

    /**
     * 处理合同
     */
    public void dealDoc(){
        System.out.println("处理合同...");
    }

    /**
     * 找合适的房源
     */
    public void searchHouse(){
        System.out.println("寻找合适的房子...");
    }
}

代理工厂类

public class MyIdeaFactory {
    public static MyIdea getInstance() {
        return new MyIdeaProxy(new MyIdeaimpl());
    }
}

主函数入口

 public static void main(String[] args) {
        //自己买房子
        MyIdeaimpl myIdeaimpl=new MyIdeaimpl();
        myIdeaimpl.buyHouse();

        System.out.println("===================================");

        //通过代理工厂买房子,此时客户并不知道代理工厂给出的是代理类还是委托类
        MyIdea myidea = MyIdeaFactory.getInstance();
        myidea.buyHouse();
    }
    
运行结果:
我想买房子
===================================
寻找合适的房子...
我想买房子
处理合同...

总结

    优点:我们可以看到,在经过代理的加持下,我们可以在不修改原有的需求下增加很多的功能,在后期的有修改需求的时候只需要替换代理类即可。

    缺点:接口里的方法都要在委托类和代理类中实现,当接口中的方法较多时就难以胜任了。

3.2 动态代理

在动态代理中,委托类和代理类是在运行时生成的。也就是说并不存在字节码文件。并且一个处理器可以动态代理出多个不同类型的委托类和接口。

实现了InvocationHandler的处理器

public class DynamicInvocationHandler implements InvocationHandler {
    private Object object;

    public DynamicInvocationHandler(Object o){
        this.object=o;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("开始....");
        method.invoke(object,args);
        System.out.println("结束...");
        return null;
    }
}

我们再来创建一个接口和委托类

public interface MyIdea2 {
    void buyCar();
}
public class MyIdea2impl implements MyIdea2{
    @Override
    public void buyCar() {
        System.out.println("我想买车车...");
    }
}

主函数

//我们可以看到MyIdea和MyIdea2是不同的接口,里面的方法也不一样。但是可以复用同一个代理类
public static void main(String[] args) {
    MyIdeaimpl myIdeaimpl=new MyIdeaimpl();
    MyIdea2impl myIdea2iml=new MyIdea2impl();

    DynamicInvocationHandler dynamicInvocationHandler=new DynamicInvocationHandler(myIdeaimpl);
    DynamicInvocationHandler dynamicInvocationHandler2=new DynamicInvocationHandler(myIdea2iml);

    MyIdea dynaMyIdea = (MyIdea) Proxy.newProxyInstance(MyIdeaimpl.class.getClassLoader(), MyIdeaimpl.class.getInterfaces(), dynamicInvocationHandler);
    dynaMyIdea.buyHouse();

    MyIdea2 dynaMyIdea2 = (MyIdea2) Proxy.newProxyInstance(MyIdea2impl.class.getClassLoader(), MyIdea2impl.class.getInterfaces(), dynamicInvocationHandler2);
    dynaMyIdea2.buyCar();
}

运行结果:
开始....
我想买房子
结束...
开始....
我想买车车...
结束...

总结:

1、通过这个动态代理类生成的代理对象不依赖具体的委托类和接口,可以复用这个动态代理类。实现了AOP功能,可以给程序提供日常的日志记录,访问统计,统一异常处理等操作。

2、再来说说缺点,动态代理也有它的缺点和局限性,一个是性能方面,动态代理的性能比较差。第二个他是面向接口的编程,就是它始终无法摆脱interface的枷锁。

4. cglib和jdk代理的区别

cglibjdk
生成代理类速度
代理类执行速度
能否对普通类进行代理不能
能否对接口进行代理
能否对final类进行代理不能
能否对final方法进行代理不能
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值