java代理模式

代理模式

代理模式(Proxy Pattern)是一种结构型设计模式,它允许你提供一个代理对象来控制对实际对象的访问。代理对象通常在客户端和目标对象之间充当中间人,可以在访问实际对象之前或之后执行某些操作。代理模式有多种用途,例如:

  • 延迟初始化:只在实际需要时才创建目标对象。
  • 访问控制:控制对目标对象的访问权限。
  • 日志记录:在方法调用前后记录日志。
  • 缓存:在代理类中实现缓存机制,减少目标对象的调用

在java中代理模式分几种常见模式:

1.静态代理

静态代理是指在编译时就确定的代理类。代理类和目标类实现相同的接口,代理类中持有目标类的实例,并在调用方法前后加入自定义逻辑。
请添加图片描述
简单理解:两个继承父类的兄弟,哥哥和弟弟,哥哥想要找父亲要点钱,叫弟弟去已自己的名义要然后交给哥哥

案例:

public interface BuyInter {

    void buyFlower();
}
public class BlackAgency implements BuyInter{
    private BuyInter buyInter;

    public BlackAgency() {
        this.buyInter = new User();
    }

    @Override
    public void buyFlower() {
        System.out.println("我是中介");

        buyInter.buyFlower();
    }
}
public class User implements BuyInter{
    @Override
    public void buyFlower() {
        System.out.println("我买了鲜花");
    }
}

    public static void main(String[] args) {
//        普通静态代理
        BuyInter buyInter = new BlackAgency();  //客户端不出现实际买鲜花的对象
        buyInter.buyFlower();

2.动态代理

动态代理是指在运行时动态生成代理类。Java 提供了 java.lang.reflect.Proxy 和 java.lang.reflect.InvocationHandler 来实现动态代理。
请添加图片描述

使用 java.lang.reflect.InvocationHandler实现动态代理案例

//必须实现一个接口,和静态代理一样
public interface UserService {

    void addUser(String name);
    void deleUser();
}

public class UserServerImpl implements UserService {
    @Override
    public void addUser(String name) {
        System.out.println("我是添加方法: "+ name);
    }

    @Override
    public void deleUser() {
        System.out.println("我是删除方法: ");
    }
}

public class LoggingInvocationHandler implements InvocationHandler {
    private final Object target;

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

//代理商的模式发生了改变
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.print("调用方法前=====方法名: " + method.getName());
        if (args != null && args.length > 0) {
            System.out.println("::参数方法: " + args[0]);
        } else {
            System.out.println("::没有参数");
        }

        Object invoke = method.invoke(target,args);
        System.out.println("调用方法后=====方法名: "+method.getName());
        return invoke;
    }
}
//主函数main
//        使用jdk动态代理
        UserService userServer = new UserServerImpl();
        LoggingInvocationHandler handler = new LoggingInvocationHandler(userServer);
        UserService user = (UserService)Proxy.newProxyInstance(
                UserService.class.getClassLoader(),
                new Class<?>[]{UserService.class},
                handler
        );
        user.addUser("张三");
        user.deleUser();

在代理商方法体中有三个参数,分别是

  • Object proxy:代理对象。这个参数是由 Proxy 类动态生成的代理实例。我们可以对其进行操作,但通常在 invoke 方法中并不使用这个参数。如果你需要知道哪个代理调用了该方法,可以用它。
  • Method method:被调用的 Method 对象。这个参数描述了被代理对象上正在调用的方法,你可以通过它获取方法的名称、返回类型、参数类型等信息。
  • Object[] args:调用方法的参数。这个参数是一个对象数组,包含代理方法调用时传入的所有参数。根据方法的参数类型,可以对这个数组进行适当的处理,例如调用目标对象方法时传递这些参数。

创建代理

  • **InvocationHandler **:调用 Proxy.newProxyInstance 方法来创建一个代理对象,并将其强制转换为 Calculator 类型。Proxy.newProxyInstance 方法用于动态创建一个代理类的实例。
  • calculator.getClass().getClassLoader(),:这一行代码指定了类加载器。代理类的创建需要使用目标对象的类加载器来加载代理类。这里我们使用 calculator 实例的类加载器。
  • new Class<?>[]{Calculator.class}:这一行代码指定了代理类实现的接口。由于我们希望代理对象实现 Calculator 接口,因此传入一个包含 Calculator.class 的数组。
  • new CalculatorInvocationHandler(calculator));:最后,我们创建了一个 CalculatorInvocationHandler 实例,并将其传递给 Proxy.newProxyInstance 方法。CalculatorInvocationHandler 类实现了 InvocationHandler 接口,并且包装了 calculator 对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值