java.lang.reflect 静态代理 动态代理

代理模式

静态代理

什么是静态代理?

当前类A不能直接访问目标类C时,需要通过手工实现一个中介类B来访问C。这就是静态代理

代理模式的作用?

控制访问、功能增强

示例(静态代理)

Factory 厂家

Merchant 商家

UserXiaoMing 用户

Sell 公共行为接口(卖东西)

/*
 * 小黄GPU厂家 不对用户直销 只给商家 问就是合作关系量大
 * */
public class Factory implements Sell {
    @Override
    public int sellGpu() {
        return 500;
    }
}

/*
 * 华珂商家(静态代理,手动实现的代理)
 * */
public class Merchant implements Sell {
    
    private Factory factory = new Factory();

    // 做代理(做中介,赚大钱)
    @Override
    public int sellGpu() {
        return factory.sellGpu() + 888;
    }
}


public interface Sell {
    int sellGpu();
}


public class UserXiaoMing {
    public static void main(String[] args) {
        System.out.println("xiaoming 买 GPU 需要付出的钱是 : " + new Merchant().sellGpu());
    }
}

// 控制台输出:
xiaoming 买 GPU 需要付出的钱是 : 1388

静态代理优缺点

  • 静态代理缺点:

  • 1、当 Sell 接口增加另外的 sellCpu() sellMemory() 时, 厂家、商家 都要变动,不解耦

  • 2、当 Factory 厂家不断增加时, 相应的 商家也会不断增加,类膨胀

  • 静态代理好处:

  • 容易实现,容易理解, user 不能直接访问 厂家,需要中介类Merchant去访问

动态代理

什么是动态代理?

java运行时,调用jdk接口通过底层反射机制自动给你生成 Merchant 商家1、Merchant 商家2 、Merchant 商家3 …

这就叫做动态代理,发现与静态代理的不同点了吗? 不需要手动自己去写商家类了

如何使用动态代理?

1、Java反射包类与接口

好麻烦,必须得构建初 handler 对象先,

再去调用 Proxy.newProxyInstance(loader,interfaces,handler);

示例

厂商+公共接口

/*
 * 电脑厂商 不直接对用户销售
 * */
public class ComputerFactory implements Sell {
    @Override
    public float sellCpu() {
        return 888.999f;
    }

    @Override
    public float sellMemory(int buyNumbs) {
        return buyNumbs * 499.99f;
    }

    @Override
    public float sellPig() {
        return 0;
    }
}

/*
 * 肉类厂商 不直接对用户销售
 * */
public class MeatsFactory implements Sell {
    @Override
    public float sellCpu() {
        return 0f;
    }

    @Override
    public float sellMemory(int buyNumbs) {
        return 0;
    }

    @Override
    public float sellPig() {
        return 15.55f;
    }
}

/*
 * 厂家公共行为出口
 * */
public interface Sell {
    float sellCpu();

    float sellMemory(int buyNumbs);

    float sellPig();
}

动态代理类

InvocationHandler.invoke 核心

public class Handler implements InvocationHandler {
    // target: 代理对象
    private Object target;

    // input: 输入厂家对象
    public Object getProxy(Object input) {
        this.target = input;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 获取到公共接口对应方法
        Object res = method.invoke(target, args);
        // 对公共接口方法进行 增强逻辑/业务逻辑/中介加钱逻辑
        if (method.toString().contains("sellCpu")) {
            res = (float) res + 2000.00f;
        } else if (method.toString().contains("sellMemory")) {
            res = (float) res - 10000.00f;
        }
        return res;
    }
}

测试类

public class XiaoNiuUser {
    public static void main(String[] args) {
        Handler handler = new Handler();

        Sell computerProxy = (Sell) handler.getProxy(new ComputerFactory());
        System.out.println("真坑啊!厂家卖 888.999,到你这就卖 sellCpu : " + computerProxy.sellCpu());
        System.out.println("真坑啊!厂家卖 499.99/根,到你这就卖 sellMemory :" + computerProxy.sellMemory(10));

        Sell meatsProxy = (Sell) handler.getProxy(new MeatsFactory());
        System.out.println("真坑啊!厂家卖 15.55,到你这就卖 sellPig :" + meatsProxy.sellPig());
    }
}

控制台:
真坑啊!厂家卖 888.999,到你这就卖 sellCpu : 2888.999
真坑啊!厂家卖 499.99/根,到你这就卖 sellMemory :-5000.1
真坑啊!厂家卖 15.55,到你这就卖 sellPig :15.55

动态代理好处: 看上面代码,没有去修改任何厂商的代码,就能直接加钱卖。 相当于在 厂商 – [黑商] --用户 中间包装了一层 “黑商” ,符合开闭原则。

2、CGLIB动态代理

别人封装好工具类了 直接用

示例

动态代理优缺点

缺点:

优点:

1)代理类数量可以很少

2)当你修改了接口中的方法时,不会影响代理类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值