Java的静态代理和动态代理

这边的东西全部来自 https://itbaima.net/document

静态代理

代理模式简介

就好比我开了个大棚,里面栽种的西瓜,那么西瓜成熟了是不是得去卖掉赚钱,而我们的西瓜非常多,一个人肯定卖不过来,肯定就要去多找几个开水果摊的帮我们卖,这就是一种代理。实际上是由水果摊老板在帮我们卖瓜,我们只告诉老板卖多少钱,而至于怎么卖的是由水果摊老板决定的。

代码实现

卖瓜版

  1. 卖瓜行为
public interface Shopper {

    //卖瓜行为
    void saleWatermelon(String customer);
}
  1. 卖瓜行为的实现(被代理类
    然后需要实现一下卖瓜行为,也就是我们要告诉老板卖多少钱,这里就直接写成成功出售:
public class ShopperImpl implements Shopper{

    //卖瓜行为的实现
    @Override
    public void saleWatermelon(String customer) {
        System.out.println("成功出售西瓜给 ===> "+customer);
    }
}
  1. 代理卖瓜行为(代理类

最后老板代理后肯定要用自己的方式去出售这些西瓜,成交之后再按照我们告诉老板的价格进行出售:

public class ShopperProxy implements Shopper{

    private final Shopper impl;

    public ShopperProxy(Shopper impl){
        this.impl = impl;
    }

    //代理卖瓜行为
    @Override
    public void saleWatermelon(String customer) {
        //首先进行 代理商讨价还价行为
        System.out.println(customer + ":哥们,这瓜多少钱一斤啊?");
        System.out.println("老板:两块钱一斤。");
        System.out.println(customer + ":你这瓜皮子是金子做的,还是瓜粒子是金子做的?");
        System.out.println("老板:你瞅瞅现在哪有瓜啊,这都是大棚的瓜,你嫌贵我还嫌贵呢。");
        System.out.println(customer + ":给我挑一个。");

        impl.saleWatermelon(customer);   //讨价还价成功,进行我们告诉代理商的卖瓜行为
    }
}
  1. 测试

现在我们来试试看:

public class Main {
    public static void main(String[] args) {
        Shopper shopper = new ShopperProxy(new ShopperImpl());
        shopper.saleWatermelon("小强");
    }
}

这样的操作称为静态代理,也就是说我们需要提前知道接口的定义并进行实现才可以完成代理

简略版

public class pox {
    public static void main(String[] args) {
        F1 f1=new F3(new F2());
        f1.f1("proxy");
        //F3proxy
        //F2proxy
        System.out.println(f1.getClass());
        // F3
    }
}

interface F1{
    void f1(String s);
}
//被代理类
class F2 implements F1{
    @Override
    public void f1(String s2) {
        System.out.println("F2"+s2);
    }
}
//代理类
class F3 implements F1{
   private final F1 f2;
   public F3(F1 f2){
       this.f2=f2;
   }
    @Override
    public void f1(String s3) {
        System.out.println("F3"+s3);
        f2.f1(s3);
    }
}

动态代理

动态代理实现的要求

1. 接口的要求

  • 基于接口:动态代理工作于接口层面。这意味着只能代理接口,而不是类。所有被代理的方法必须在一个或多个接口中定义。

2. 实现 InvocationHandler

  • 创建 InvocationHandler 实现:这个接口是动态代理的核心。你需要提供一个 InvocationHandler 的实现,在其中定义方法调用的处理逻辑。每次代理接口的方法被调用时,都会转发到这个处理器的 invoke 方法。

3. 使用 Proxy 类生成代理对象

  • 使用 Proxy.newProxyInstance 方法:这个方法用于在运行时动态创建代理类的实例。它需要三个参数:
    • ClassLoader:用来定义代理类的类加载器
    • Interfaces:代理类需要实现的接口列表
    • InvocationHandler你实现的调用处理器

4. 代理实例的使用

  • 作为接口实例使用:动态代理返回的对象是实现了指定接口的代理实例。你可以像使用实现了接口的普通实例一样使用这个代理实例

5. 方法调用的处理

  • 方法转发逻辑InvocationHandlerinvoke 方法是所有方法调用的中转站。你可以在这里实现方法调用前后的自定义逻辑,例如日志记录、权限检查、事务处理等。

代理类 (DynamicProxyHandler)的代码模板

class DynamicProxyHandler implements InvocationHandler {
    private final Object target;

    public DynamicProxyHandler(Object target) {
        this.target = target;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method: " + method.getName());
        Object invoke = method.invoke(target, args);
        System.out.println("After method: " + method.getName());
        return invoke;
    }
}

接口和测试

1. 无返回值无参数的接口 (T1)

interface T1 {
    void noRnoP();
}

1.1测试

@Test
public void t1() {
    T1 t1 = (T1) Proxy.newProxyInstance(T1.class.getClassLoader(),
                new Class[]{T1.class},
                new DynamicProxyHandler(new T1() {
                    @Override
                    public void noRnoP() {
                        System.out.println("T1 is called");
                    }
                }));
        t1.noRnoP();
        System.out.println(t1.getClass());
}

2. 无返回值有参数的接口 (T2)

interface T2 {
    void noRhaveP(String s);
}

2.1 测试

@Test
public void t2() {
    T2 t2 = (T2) Proxy.newProxyInstance(T2.class.getClassLoader(),
                new Class[]{T2.class},
                new DynamicProxyHandler(new T2() {
                    @Override
                    public void noRhaveP(String s) {
                        System.out.println("T2 is called param is" + s);
                    }
                }));
        t2.noRhaveP("T2");
        System.out.println(t2.getClass());
}

3. 有返回值无参数的接口 (T3)

interface T3 {
    String haveRnoP();
}

3.1 测试

@Test
public void t3() {
    T3 t3 = (T3) Proxy.newProxyInstance(T3.class.getClassLoader(),
                new Class[]{T3.class},
                new DynamicProxyHandler(new T3() {
                    @Override
                    public String haveRnoP() {
                        System.out.println("T3 is called");
                        return "T3 is returned";
                    }
                }));
        String s = t3.haveRnoP();
        System.out.println(s);
        System.out.println(t3.getClass());
}

4. 有返回值有参数的接口 (T4)

interface T4 {
    String haveRhaveP(String s);
}

4.1 测试

@Test
public void t4() {
   T4 t4 = (T4) Proxy.newProxyInstance(T4.class.getClassLoader(),
                new Class[]{T4.class},
                new DynamicProxyHandler(new T4() {
                    @Override
                    public String haveRhaveP(String s) {
                        System.out.println("T4 is called param is" + s);
                        return "T4 is returned param is" + s;
                    }
                }));
        String s1 = t4.haveRhaveP("T4");
        System.out.println(s1);
        System.out.println(t4.getClass());
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值