Java代理的实现(代码)

本文介绍了Java中代理模式的实现,包括静态代理和动态代理。静态代理通过实现目标类接口来增强功能,适用于单一目标类。动态代理则通过代理类模板动态生成代理对象,适用于多个目标类,避免了重复代码。

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

简单来说,代理就是不改变原有对象的基础上,对原有功能进行增强。java的三种创建代理对象的方式有三种,分别是静态代理、基于jdk的动态代理和基于CGLIB的动态代理。下面主要来看一下静态代理和动态代理代码方面的实现方式(用于理解java的代理机制)。

静态代理:

如下图所示,代理类通过实现目标类的接口,来对目标类的方法进行代理(代理主要针对的是方法),之所以通过接口,而不直接去找目标类,是因为直接去找目标类一是代码会写“死”,不够灵活,二是当有多个目标类时,代理起来太过繁琐而且容易出现矛盾,而接口是一个行业标准,对外开放,代理类通过接口实现对目标类的代理更加灵活,接口下面可以有很多实现类。

下面以购买衣服为例,来解释一下静态代理,如下图所示,我们想要买衣服,但是我们找不到生产衣服的工厂或者无法进行直接购买,这时候就需要去找代理商,代理商不光有工厂可以卖衣服的功能,同时还有强化的一些其他功能,售后服务等。回到java代理机制,也就是代理对象包含目标对象,在实现了目标对象方法的同时,添加了一些其他功能进行了强化,实现代码如下:

一、定义一个目标类接口:

public interface BuyClothes {
    //购买衣服的方法
    void buy(String size);
}

二、目标类(卖衣服的工厂),实现买衣服的接口和他的方法:

public class ClothesFactory implements BuyClothes{
    @Override
    public void buy(String size) {
        System.out.println("您得到了一件尺码是"+size+"的衣服");
    }
}

三、定义代理类(代理商),实现购买衣服的接口,就相当于把目标类的事做了:

public class ProxyClothes implements BuyClothes{
    //目标类对象
    public ClothesFactory clothesFactory;
    //定义有参构造方法,创建代理类的时候,给他把目标类放进去
    public ProxyClothes(ClothesFactory clothesFactory) {
        this.clothesFactory = clothesFactory;
    }

    @Override
    public void buy(String size) {
        //售前服务
        frontService();

        //通过目标类对象把目标类方法调起来
        clothesFactory.buy(size);

        //售后服务
        endService();
    }
    public void frontService(){
        System.out.println("欢迎购买衣服,我们为您测量尺码");
    }
    public void endService(){
        System.out.println("欢迎下次购买!");
    }
}

四、写一个测试类测试一下(结果如下图),一个静态代理的示例就写完了!

public class Test {
    public static void main(String[] args) {
        ClothesFactory clothesFactory=new ClothesFactory();
        ProxyClothes proxyClothes=new ProxyClothes(clothesFactory);
        //直接去原工厂购买衣服(不使用代理类)
        clothesFactory.buy("xxl");
        System.out.println("======================");
        //通过代理商购买衣服(使用代理类)
        proxyClothes.buy("xxl");
    }
}

运行结果:

目标类

==================

代理类

动态代理

继续上面的场景,那么问题来了,如果好多工厂都要让他代理,该怎么办呢?难道要每次添加目标工厂都要去改代码吗,答案肯定不是,使用动态代理,写一个生成代理类的模板,根据需要动态的生成代理类就可以了,代码如下:

一、在上面场景的基础上,我们添加了卖鞋的接口;

public interface BuyShoes {
    void buy(String size);
}

二、写一个卖鞋的目标类(卖鞋的工厂)

public class ShoesFactory implements BuyShoes{
    @Override
    public void buy(String size) {
        System.out.println("您得到了一件尺码为"+size+"的鞋子");
    }
}

三、以下代码就可以理解为一个生成代理类的模板类;

public class Company implements InvocationHandler {
    //目标对象,不知道是什么,所以写Object类,就是多态,父类引用可以指向任何子类对象
    private Object object;

    public Object getObject() {
        return object;
    }
    //需要代理什么类,就调用set方法放进来
    public void setObject(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //售前服务
        frontService();
        //不知道调用什么对象的什么方法,就使用通用的方法
        method.invoke(object,args);
        //售后服务
        endService();
        return null;
    }
    public void frontService(){
        System.out.println("欢迎购买衣服,我们为您测量尺码");
    }
    public void endService(){
        System.out.println("欢迎下次购买!");
    }

    //获取代购人员,通过set方法拿到具体对象后,生成代理类
    public Object getProxyInstance(){
        Object obj=Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(),this);
        return obj;
    }
}

四、测试

public static void main(String[] args) {
        //动态代理
        ClothesFactory clothesFactory=new ClothesFactory();
        ShoesFactory shoesFactory=new ShoesFactory();
        Company company=new Company();
        //代理衣服
        //调用set方法把clothes这个对象放进去
        company.setObject(clothesFactory);
        //获取代理类,父类无法调用子类方法,做一个强制类型转换
        BuyClothes object=(BuyClothes)company.getProxyInstance();
        object.buy("xxl");
        System.out.println("=================================");
        //代理鞋子
        company.setObject(shoesFactory);
        BuyShoes object1=(BuyShoes) company.getProxyInstance();
        object1.buy("42");

    }

测试结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值