JAVA代理模式

JAVA代理模式

代理模式:通过代理类访问被代理类,用于对被代理类功能的加强与功能的扩展

用户可以通过访问代理类来调用被代理类的功能

img

代理模式类图:

代理(Proxy)模式结构图

假设:用户需要验证信息后访问管理员

角色:

  • 用户:用于访问管理员对象
  • 管理员:对数据进行操作
  • 管理员代理:代表管理员进行数据操作,并对原来的管理员进行增强

静态代理

静态代理模式在不改变目标对象的前提下,实现了对目标对象的功能扩展。

不足:静态代理实现了目标对象的所有方法,一旦目标接口增加方法,代理对象和目标对象都要进行相应的修改,增加维护成本。

在这里插入图片描述

管理员接口

Admin:代理类与被代理的委托类共有的方法,用于让代理与委托的方法统一

public interface Admin {
    void update();
    void select();
}

委托类

AdminDelegatorInter:委托类的接口,用于实现委托对象的多态实现

public interface AdminProxyInter extends Admin {
}

AdminDelegator:管理员实现类(委托类)

public class AdminDelegator implements AdminDelegatorInter {

    @Override
    public void update() {
        System.out.println("上传数据");
    }

    @Override
    public void select() {
        System.out.println("查询数据");
    }
}

UserAdminDelegator:用户管理员实现类(委托类)

public class UserAdminDelegator implements top.xtijie.staticProxy.delegator.AdminDelegatorInter {
    @Override
    public void update() {
        System.out.println("上传用户数据");
    }

    @Override
    public void select() {
        System.out.println("查询用户数据");
    }
}

代理类

AdminProxyInter:代理类的接口,实现代理对象的多态实现

public interface AdminProxyInter extends Admin {
}

AdminProxy:代理管理员的实现类(代理类)

import top.xtijie.staticProxy.delegator.AdminDelegatorInter;

public class AdminProxy implements AdminProxyInter {

    private final AdminDelegatorInter adminDelegator;

    public AdminProxy(AdminDelegatorInter adminDelegator) {
        this.adminDelegator = adminDelegator;
    }

    @Override
    public void update() {
        System.out.println("查询管理员权限");
        adminDelegator.update();
    }

    @Override
    public void select() {
        System.out.println("查询查询权限");
        adminDelegator.select();

    }
}

UserAdminProxy:代理用户管理员实现类(代理类)

import top.xtijie.staticProxy.delegator.AdminDelegatorInter;

public class UserAdminProxy implements AdminProxyInter {

    private final AdminDelegatorInter delegatorInter;

    public UserAdminProxy(AdminDelegatorInter delegatorInter) {
        this.delegatorInter = delegatorInter;
    }

    @Override
    public void update() {
        System.out.println("查询用户管理权限");
        delegatorInter.update();
    }

    @Override
    public void select() {
        System.out.println("查询用户权限");
        delegatorInter.select();
    }
}

用户访问

public class APP {
    public static void main(String[] args) {

        // 创建管理员委托实例
//        AdminDelegatorInter adminDelegator = new AdminDelegator();
        AdminDelegatorInter adminDelegator = new UserAdminDelegator();

        // 创建代理管理员实例
//        AdminProxyInter adminProxy = new AdminProxy(adminDelegator);
        AdminProxyInter adminProxy = new UserAdminProxy(adminDelegator);
        adminProxy.update();
    }
}

代理类的中需要有委托类的对象

用户只需创建不同的委托对象,并将委托对象放入不同的代理对象,即可实现对功能的扩展

动态代理

Java自带动态代理类:Proxy

为解决静态代理对象必须实现接口的所有方法的问题,Java给出了动态代理,动态代理具有如下特点:

  1. Proxy对象不需要implements接口
  2. Proxy对象的生成利用JDK的Api,在JVM内存中动态的构建Proxy对象。需要使用

Java动态代理中,代理对象不需要自己手动创建,由Java自带对象Proxy进行创建

Invocation:Java进行动态代理时需要的调用器

在这里插入图片描述

管理员接口

Admin:代理类与被代理的委托类共有的方法,用于让代理与委托的方法统一

public interface Admin {
    public void select();

    public void update();
}

调用器

AdminInvocation:管理员调用器,通过实现InvocationHandler接口,可以实现对委托类的调用

import top.xtijie.dynamicProxy.delegator.AdminDelegator;

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

public class AdminInvocation implements InvocationHandler {

    private final AdminDelegator adminDelegator;

    public AdminInvocation(AdminDelegator adminDelegator) {
        this.adminDelegator = adminDelegator;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("检查权限");
        return method.invoke(adminDelegator, args);
//        return proxy;
    }
}

invoke方法:

参数:

  • proxy:代理对象
  • method:调用的方法
  • args:方法中的参数

返回值:

  • 当返回method.invoke(adminDelegator, args);时,代理对象将执行当前方法中的其他代码,并返回代理对象
  • 当返回参数中的proxy时,代理对象将直接返回委托类中的方法,不执行当前方法中的其他代码,不对功能进行扩展

委托类

AdminDelegator:委托类

import top.xtijie.dynamicProxy.mapp.Admin;

public class AdminDelegator implements Admin {
    @Override
    public void update() {
        System.out.println("上传数据");
    }

    @Override
    public void select() {
        System.out.println("查询数据");
    }
}

用户访问

public class APP {
    public static void main(String[] args) {
		
        AdminDelegator adminDelegator = new AdminDelegator();

        AdminInvocation adminInvocation = new AdminInvocation(adminDelegator);

        Admin proxy = (Admin) Proxy.newProxyInstance(
                adminDelegator.getClass().getClassLoader(),
                new Class[]{Admin.class},
                adminInvocation);
        proxy.update();
    }

}

用户仍然需要创建管理员委托对象,并将委托类置于调用器中,调用器执行完方法后会返回当前的代理对象

委托类创建Proxy.newProxyInstance()的参数描述:

  • adminDelegator.getClass().getClassLoader():管理员委托类的类加载器,用于Java加载该对象
  • new Class[]{Admin.class}:委托类所实现的接口的Class对象的数组,用于指定当前委托类的接口
  • adminInvocation:委托类的调用加载程序

参考:

Java代理(Proxy)模式 - 简书 (jianshu.com)

设计模式之代理模式(Proxy Pattern) - 有点小白的菜鸟 - 博客园 (cnblogs.com)

(44条消息) Java中InvocationHandler接口中第一个参数proxy详解_艾米莉Emily的博客-CSDN博客_invocationhandler接口

Java代理模式是一种结构型设计模式,其目的是为其他对象提供一种代理以控制对这个对象的访问。代理对象可以在客户端和目标对象之间充当中介,以便于客户端访问目标对象时,可以在不改变目标对象的情况下添加一些额外的功能,比如安全性、远程访问、缓存等。 在Java中,代理模式可以通过两种方式实现:静态代理和动态代理。静态代理需要手动编写代理类,而动态代理可以在运行时通过反射机制动态生成代理类,更加灵活。 举个例子,假设我们有一个接口`Subject`,其中定义了一些方法。我们希望在调用这些方法时,增加一些额外的日志记录功能。我们可以编写一个代理类`SubjectProxy`,在代理类中实现接口方法并调用目标对象的方法,同时在方法前后添加日志记录的代码。客户端则通过代理类访问目标对象。 静态代理示例代码如下: ```java public interface Subject { void doSomething(); } public class RealSubject implements Subject { @Override public void doSomething() { System.out.println("RealSubject do something."); } } public class SubjectProxy implements Subject { private Subject realSubject; public SubjectProxy(Subject realSubject) { this.realSubject = realSubject; } @Override public void doSomething() { System.out.println("Before do something."); realSubject.doSomething(); System.out.println("After do something."); } } public class Client { public static void main(String[] args) { Subject realSubject = new RealSubject(); Subject subjectProxy = new SubjectProxy(realSubject); subjectProxy.doSomething(); } } ``` 动态代理示例代码如下: ```java public class SubjectHandler implements InvocationHandler { private Object target; public SubjectHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before " + method.getName()); Object result = method.invoke(target, args); System.out.println("After " + method.getName()); return result; } } public class Client { public static void main(String[] args) { Subject realSubject = new RealSubject(); InvocationHandler handler = new SubjectHandler(realSubject); Subject subjectProxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler); subjectProxy.doSomething(); } } ``` 无论是静态代理还是动态代理代理模式都可以在不改变目标对象的情况下,为其添加额外的功能,提高代码的可复用性和灵活性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值