代理模式

本文详细解析了Java中静态代理和动态代理的概念及其实现方式,包括如何通过接口和代理类进行方法调用的预处理,同时对比了JDK动态代理和CGLIB的优缺点及适用场景。

1、静态代理

在程序运行前,代理类的class文件已经生成(程序员自己创建)。

例子:

厂家货物交给经销商去卖。这里经销商是代理类,厂家具有进出货功能(被代理类)。代码实现:

创建一个接口:

public interface Shop {

    /**
     * 进货
     * @return
     */
    Integer purchase();

    /**
     * 卖货
     * @return
     */
    Integer sale();

}

被代理类,实现接口:

public class Shop4s implements Shop {

    /**
     * 进货量
     */
    int purchase;
    /**
     * 售卖量
     */
    int sale;

    public Shop4s(int purchase,int sale) {
        this.purchase = purchase;
        this.sale = sale;
    }


    @Override
    public Integer purchase() {
        System.out.println("进货量:" + purchase);
        return purchase;
    }

    @Override
    public Integer sale() {
        System.out.println("售卖量:" + sale);
        return sale;
    }
}

创建代理类,实现接口:

public class Shop4sProxy implements Shop{

    /**
     * 被代理对象
     */
    Shop4s shop4s;

    public Shop4sProxy(Shop shop) {
        this.shop4s = (Shop4s) shop;
    }

    /**
     * 代理进货方法
     * @return
     */
    @Override
    public Integer purchase() {
        return shop4s.purchase();
    }

    /**
     * 代理售货方法
     * @return
     */
    @Override
    public Integer sale() {
        return shop4s.sale();
    }
}

测试:

public static void main(String[] args) {
        // 被代理对象
        Shop beiJing4s = new Shop4s(10,2);

        // 代理对象
        Shop beiJing4sProxy = new Shop4sProxy(beiJing4s);

        // 代理商(代理对象) 进货、卖货
        beiJing4sProxy.purchase();
        beiJing4sProxy.sale();
    }

 

2、动态代理

代理类在程序运行时创建的代理方式被成为动态代理。Java动态代理是利用反射机制生成一个实现代理接口的代理类,在调用具体方法前调用InvokeHandler来处理。

2.1、jdk自带

定义一个接口:

public interface Shop {

    /**
     * 获取商品名称
     */
    void getShopName();
}

创建被代理类:

public class Shop4s implements Shop{

    /**
     * 商品名
     */
    String name;

    public Shop4s(String name) {
        this.name = name;
    }

    @Override
    public void getShopName() {
        System.out.println("该商品名是:" + name);
    }
}

需要实现InvokeHandler接口:

public class CommonDynamicProxy<T> implements InvocationHandler {

    // 通用的被代理对象
    T commonCoverDynamicProxy;

    public CommonDynamicProxy(T commonCoverDynamicProxy) {
        this.commonCoverDynamicProxy = commonCoverDynamicProxy;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("jdk动态代理执行" + method.getName() + "方法");

        method.invoke(commonCoverDynamicProxy, args);

        return proxy;
    }
}

测试:

public static void main(String[] args) {
        // 被代理对象
        Shop beiJing4s = new Shop4s("beiJing4s 路虎 E30");

        // 创建一个与代理对象相关联的InvocationHandler
        InvocationHandler shopDynamicProxy = new CommonDynamicProxy<Shop>(beiJing4s);

        // 创建一个代理对象; 会执行 invoke()
        Shop shop = (Shop) Proxy.newProxyInstance(
                Shop.class.getClassLoader(),
                new Class<?>[]{Shop.class},
                shopDynamicProxy);

        shop.getShopName();
    }

2.2、cjlib

代码实现和jdk类似,不过需要引入jar包。代理类需要实现MethodInterceptor。

没有写这个实例,感兴趣的可以自行搜索。在这里推荐一篇文章:https://blog.youkuaiyun.com/zhangyong01245/article/details/90644933

2.3、jdk与cjlib区别

1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP。

2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP(<aop:aspectj-autoproxy proxy-target-class="true"/>)。

3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换。

4、对于singleton的代理对象或者具有实例池的代理,因为无需频繁的创建代理对象,所以比较适合采用CGLib动态代理,反正,则比较适用JDK动态代理。

参考

https://blog.youkuaiyun.com/qq_40244666/article/details/89710673

https://www.cnblogs.com/panning/p/10662417.html

https://blog.youkuaiyun.com/bu2_int/article/details/60150319?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值