复习代理模式

静态代理

被代理对象实现的接口:

/**
 * @author xwm
 * @email 2825902051@qq.com
 * @date 2021/9/13 0013
 * @time 18:51
 */
public interface Computer {
    //出售电脑
    double sellComputer(double price);
}

被代理对象:

public class Lenovo implements Computer{

    @Override
    public double sellComputer(double price) {
        System.out.println("执行目标对象 do sellComputer() 方法\n花费了"+price+"元");
        return price;
    }
}

使用静态代理代理Lenovo对象:

package Proxy;

/**
 * @author xwm
 * @email 2825902051@qq.com
 * @date 2021/9/13 0013
 * @time 18:55
 */
public class StaticProxy implements Computer{
    private Lenovo target;

    public StaticProxy(Lenovo target) {
        this.target = target;
    }


    @Override
    public double sellComputer(double price) {
        System.out.println("static proxy...");
        return target.sellComputer(price);
    }

    public static void main(String[] args) {
        Lenovo lenovo = new Lenovo();
        StaticProxy staticProxy = new StaticProxy(lenovo);
        double price=4000.0;
        staticProxy.sellComputer(price);
    }
}

总结

  • 静态代理在编译的时候·就生成了代理对象,而动态代理需要在运行时生成代理对象的字节码来构造对象。
  • 粒度较大,修改参数和返回值需要在调用方法前后,并且如果需要添加业务逻辑要先写死在代理对象的方法中,时机不好控制,不灵活。

JDK动态代理

实现InvocationHandler接口并重写方法

package Proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author xwm
 * @email 2825902051@qq.com
 * @date 2021/9/13 0013
 * @time 19:41
 */
public class JdkProxy implements InvocationHandler {
    private Object target;

    public JdkProxy(Object target) {
        this.target = target;
    }

    public Object getProxyInstance(){
        Object o = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        return o;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("jdk proxy ...");
        System.out.println("拿到方法参数为:"+args[0]);
        double invoke = (double) method.invoke(target, args);
        invoke=invoke-5000.0;
        System.out.println("返回值为:"+invoke);
        System.out.println("jdk proxy ...");
        return invoke;
    }

    public static void main(String[] args) {
        JdkProxy jdkProxy =new JdkProxy(new Lenovo());
        Computer proxyInstance = (Computer)jdkProxy.getProxyInstance();
        double v = proxyInstance.sellComputer(10000.0);
        System.out.println("实际费用为"+v);
    }
}

运行结果:
在这里插入图片描述
总结

  • jdk动态代理通过生成一个和目标对象有相同接口,并且类加载器相同的字节码,然后通过反射创建一个和目标对象有相同特征的代理对象,所以需要在运行时才能创建。
  • 代理的粒度较细,并且不需要像静态代理一样每个方法都要写死业务逻辑,可以修改参数和返回值,比较灵活
  • 由于生成的代理对象已经继承了Proxy所以不能在继承别的类,并且目标对象必须有接口实现

Cglib动态代理

package Proxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.Date;

/**
 * @author xwm
 * @email 2825902051@qq.com
 * @date 2021/9/13 0013
 * @time 19:03
 */
public class CglibProxy implements MethodInterceptor {
    private Object target;

    public CglibProxy(Object target) {
        this.target = target;
    }

    public Object getProxyInstance(){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        // 回调方法
        enhancer.setCallback(this);
        // 创建代理对象
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("cglib proxy ...");
        System.out.println("收到的进购费用为:"+objects[0]);
        double money=3000.0;
        Object o1 = methodProxy.invokeSuper(o, new Object[]{money});
        System.out.println("购买时间为:"+new Date());
        System.out.println("cglib proxy ...");
        return o1;
    }

    public static void main(String[] args) {
        Lenovo lenovo = new Lenovo();
        Lenovo proxyInstance = (Lenovo) new CglibProxy(lenovo).getProxyInstance();
        double v = proxyInstance.sellComputer(4000.0);
        System.out.println("实际费用为"+v);

    }
}

运行结果:
在这里插入图片描述
总结

  • 目标类必须是公共的不被finall修饰的,并且被代理对象的方法也不能被final修饰。
  • 通过继承目标对象来重写里面的方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小呆萌熊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值