Zhou Study hard, improve every day.

设计模式-代理

2023-08-28
本文 2505 字,阅读全文约需 8 分钟

1.什么是代理

有一些场景下,个人不想完成一些事情,所以需要一个人来帮助完成这件事。比如房产中介。

代理有什么用?有一些场景,个人并不是很想干这种事。

  • 比如买东西,去日本买,对于个人来说,我只想要一个东西,并不想去日本,可以找一个代理的中介帮助我们处理这个。

  • 比如打官司,对于前期的收集材料,后期的一些补充材料

2.代理分类

代理有两种实现方式:静态代理,动态代理。

它们的主要区别,静态代理会自己实现类,动态代理,则是运行时,JVM给你动态生成类,这是两者之间的主要区别。

2.1静态代理

静态代理,是自己手动实现前置接口,然后写死功能,这就是静态代理

/**
 * 租房接口
 *
 * @author Common-zhou
 * @since 2023-08-28 14:30
 */
public interface IRentHouse {

    /**
     * 租房接口,传入钱,返回是否租到
     *
     * @param money 钱
     * @return 是否租到
     */
    boolean rent(Integer money);
}

public class RealRenter implements IRentHouse {
    @Override
    public boolean rent(Integer money) {
        System.out.println("出" + money + "租房。。。");
        return true;
    }
}

public class RentHouseProxy implements IRentHouse {

    private IRentHouse iRentHouse;

    public RentHouseProxy(IRentHouse iRentHouse) {
        this.iRentHouse = iRentHouse;
    }

    @Override
    public boolean rent(Integer money) {
        System.out.println("前置的房源寻找ing......");
        System.out.println("沟通中......");

        boolean rent = iRentHouse.rent(money);

        System.out.println("后置的合同草拟,沟通......");
        return rent;
    }
}

2.2动态代理

在Java中的动态代理,需要使用以下步骤:

  1. 接口
  2. 自定义实现类
  3. 动态代理需要完成的功能,需要实现一个接口
  4. 使用Proxy.newInstance方法完成初始化,在运行时动态生成实现类。
public interface IRentHouse {

    /**
     * 租房接口,传入钱,返回是否租到
     *
     * @param money 钱
     * @return 是否租到
     */
    boolean rent(Integer money);
}

public class RealRenter implements IRentHouse {
    @Override
    public boolean rent(Integer money) {
        System.out.println("出" + money + "租房。。。");
        return true;
    }
}

public class RentHouseProxy implements IRentHouse {
    private IRentHouse iRentHouse;

    public RentHouseProxy(IRentHouse iRentHouse) {
        this.iRentHouse = iRentHouse;
    }

    @Override
    public boolean rent(Integer money) {
        System.out.println("前置的房源寻找ing......");
        System.out.println("沟通中......");

        boolean rent = iRentHouse.rent(money);

        System.out.println("后置的合同草拟,沟通......");
        return rent;
    }
}

一般真实的业务场景,比如缓存,比如日志。不可能在每一个实现类都去写这种代码,非常的麻烦,所以需要使用这种动态代理。

Proxy.newProxyInstance 是 Java 提供的用于创建动态代理对象的静态方法。它接受三个参数,详细介绍一下这些参数,以及一般传入什么值。

javaCopy codepublic static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
  1. ClassLoader (loader): 这是一个用于加载代理类的 ClassLoader。代理类是在运行时生成的,所以需要一个类加载器来加载它。通常情况下,你可以使用被代理类的 ClassLoader,也就是实现被代理接口的类的类加载器。例如,如果被代理的接口是 UserService,那么一般会传入 UserService.class.getClassLoader()
  2. Class<?>[] (interfaces): 这是一个数组,包含了代理类要实现的接口列表。动态代理对象需要实现一个或多个接口,因此你需要传入被代理接口的类类型。例如,如果你的被代理接口是 UserService,则传入 new Class<?>[] { UserService.class }
  3. InvocationHandler (h): 这是一个实现了 InvocationHandler 接口的对象,用于处理代理对象上的方法调用。InvocationHandler 接口中的 invoke 方法会在代理对象的方法调用时被触发,你可以在这个方法中实现你的逻辑。通常情况下,你会创建一个类,实现 InvocationHandler 接口,将实际对象传递给它,然后在 invoke 方法中添加你想要的处理逻辑。

综上所述,一般来说,你会将被代理接口的 ClassLoader、被代理接口的类类型数组,以及实现了 InvocationHandler 接口的处理器对象作为参数传递给 Proxy.newProxyInstance 方法。这样,当代理对象的方法被调用时,会触发处理器中的逻辑。


上一篇 log4j使用整理

Comments

Content