Java设计模式---静态代理和动态代理

本文介绍了Java中的静态代理和动态代理概念。静态代理通过创建代理类实现接口,增加了代码量但实现了业务分工。动态代理则更灵活,利用Proxy和InvocationHandler动态生成代理对象,减少了代码冗余,尤其适用于需要对多个类进行相同功能增强的情况。动态代理分为基于接口的JDK动态代理和基于类的CGLIB动态代理,JDK动态代理借助InvocationHandler的invoke方法实现方法拦截和增强。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、静态代理

假设一个场景,一个客户需要租房,然后找到中介,中介那里有很多房源。房东负责出租,那么中介就带客户去:(1)看房 (2)房东出粗(3) 签合同 (4)收中介费

①创建一个房东接口并创建一个具体的房东实现这个接口

public interface Rent {
    void rent(); //出租
}
public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("房东出租房屋");
    }
}

②创建一个代理对象(中介) 调用房东租房并附带一些其他的操作

public class Proxy {

    private Host host;

    public Proxy(Host host) {
        this.host = host;
    }
    public void rent(){
        System.out.println("带看房");
        host.rent();
        System.out.println("签合同");
        System.out.println("收房租");
    }
}

③测试

public class Client {
    public static void main(String[] args) {
        Host host = new Host();
        Proxy proxy = new Proxy(host); //中介帮房东租房子 但是呢 中介会进行一些附加的操作
        proxy.rent();
    }
}

//打印
// 带看房
// 房东出租房屋
// 签合同
// 收房租

说白了就是对某个具体的类中的方法进行了增强。不影响被代理类的操作的同时对代理类的操作进行了增强.

优点:

  • 可以时被代理的类的功能更加纯粹,不用去关注一些公共的业务
  • 公共业务交给了代理它的类,实现了业务的分工
  • 也便于公共业务发生扩展

缺点:

  • 一个被被代理的类就得产生一个代理他的类,代码量会增加,开发效率会变低。

二、动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的!
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    基于接口–JDK动态代理
    基于类:cglib动态代理

以下是基于接口的JDK动态代理、需要了解两个类:
Proxy(代理),提供创建代理类实例的静态方法
InvocationHandler(调用处理程序):每个代理对象都需要一个InvocationHandler去进行关联,代理对象调用方法时会调用InvocationHandler中的invoke方法,然后我们可以在这个方法中对被代理中的方法进行增强。

①创建一个房东接口并创建一个具体的房东实现这个接口

public interface Rent {
    void rent();
}
public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("房东出租房屋");
    }
}

②创建一个用来生成代理对象的类

//等会儿我们用这个类 ,自动生成代理类!
public class ProxyInvocationHandler implements InvocationHandler {

    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //生成一个代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(rent.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
    }

    //处理代理实例并返回处理结果  (这个方法是生成的代理类调用方法是自动调用的,相当于这个方法会拦截代理对象调用的方法 然后对该方法进行增强)
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("看房");
        Object result = method.invoke(rent, args);//通过反射 执行rent中的方法
        //打印被调用的方法的名称
       // System.out.println(method.getName());
        System.out.println("签合同");
        System.out.println("收中介费");
        return result;
    }


}

③测试

public class Client {
    public static void main(String[] args) {
        //真实角色(被代理的对象)
        Host host = new Host();
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setRent(host);//设置要代理的对象
        //拿到我们的代理对象
        Rent proxy = (Rent) pih.getProxy();
        proxy.rent();
    }
}

//执行结果打印
//看房
//房东出租房屋
//签合同
//收中介费

注意:当然 这个地方可以变得更加万能和灵活,将ProxyInvocationHandler 中的Rent换成Object,这样我们想对哪个类进行代理都行.

动态代理的好处:

  • 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务.
  • 公共业务就交给代理对象!实现业务的分工!
  • 不用像静态代理那样对于每一个需要被代理的类都手写一个代理类。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值