Java基础,代理

代理模式(Proxy Pattern)是Java设计模式中的一种结构型模式,它为其他对象提供了一种代理以控制对这个对象的访问。代理模式的主要思想是通过代理对象来代替实际对象执行某些操作,这样可以增强或控制实际对象的行为。

一、代理模式

1、什么是代理模式

代理模式提供了一个代理对象,代替实际对象处理请求。代理模式可以在不同的场景下使用,例如控制访问权限、延迟加载、提供日志记录等功能。代理模式的核心思想是:

  • 代理对象:代表实际对象(真实对象)处理客户端请求。
  • 真实对象:实际完成业务逻辑的对象。

2、代理模式的角色:

  • Subject(抽象主题):定义代理类和真实类共同实现的接口。
  • RealSubject(真实主题):实现具体的业务逻辑。
  • Proxy(代理类):在不修改真实对象的前提下,通过代理对象对真实对象的操作进行控制或增强。

二、静态代理模式

1、什么是静态代理

静态代理是在编译期间就实现的代理,它通过创建代理类并实现相同的接口来代理真实对象。静态代理在代理类中增强了方法调用的功能,但这种方式会增加系统中类的数量,因为每一个需要代理的类都需要有一个代理类。

2、静态代理的流程图

  • Client(客户端):调用代理对象的方法。
  • Proxy(代理类):代理类实现了与真实类相同的接口,在代理类中,客户端的请求会先经过代理,然后再传递给真实对象。
  • RealSubject(真实类):实现接口中的具体业务逻辑。
Client ---> Proxy ---> RealSubject

3、静态代理的执行流程

(1)、客户端通过代理对象调用接口中的方法。

(2)、代理对象会在调用接口方法时,增强功能(例如添加日志、权限检查等)。

(3)、代理对象最终会调用真实对象的对应方法来执行实际业务逻辑。

4、静态代理代码示例

1、定义接口

// 定义一个接口Subject
public interface Subject {
    void request();
}

2、实现真实类

// 实现真实类RealSubject
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject: Handling request.");
    }
}

3、实现代理类

// 实现代理类ProxySubject
public class ProxySubject implements Subject {
    private RealSubject realSubject;

    public ProxySubject(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public void request() {
        System.out.println("Proxy: Logging before request.");
        realSubject.request();
        System.out.println("Proxy: Logging after request.");
    }
}

4、编写测试类

public class StaticProxyTest {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        ProxySubject proxy = new ProxySubject(realSubject);
        
        // 客户端通过代理对象调用方法
        proxy.request();
    }
}

运行结果:

Proxy: Logging before request.
RealSubject: Handling request.
Proxy: Logging after request.

通过静态代理,我们在调用真实对象的前后增加了日志记录的功能,而不需要修改真实类的代码。这是静态代理的核心优势。

三、动态代理

1、什么是动态代理

动态代理相比静态代理更加灵活,因为动态代理不需要提前编写代理类,而是在运行时通过反射机制动态生成代理对象。Java的java.lang.reflect.Proxy类和InvocationHandler接口提供了动态代理的支持。

动态代理常用于AOP(面向切面编程)中,例如在Spring框架中,动态代理经常用于实现事务、日志、权限等横切关注点。

2、动态代理的执行流程

(1)、动态生成代理类,不需要为每一个接口创建单独的代理类。

(2)、代理类实现接口,并在调用时通过InvocationHandler调用实际对象的方法。

(3)、可以在方法调用前后插入增强功能。

3、动态代理的代码示例

1、定义接口和实现类

public interface Subject {
    void request();
}

public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject: Handling request.");
    }
}

2、实现InvocationHandler

InvocationHandler接口是Java动态代理的核心,所有的方法调用都会转发到InvocationHandlerinvoke方法中。

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

public class ProxyHandler implements InvocationHandler {
    private Object realObject;

    public ProxyHandler(Object realObject) {
        this.realObject = realObject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Proxy: Logging before request.");
        Object result = method.invoke(realObject, args);
        System.out.println("Proxy: Logging after request.");
        return result;
    }
}

3、创建动态代理

通过Proxy.newProxyInstance()方法来创建代理对象。

import java.lang.reflect.Proxy;

public class DynamicProxyTest {
    public static void main(String[] args) {
        // 创建真实对象
        RealSubject realSubject = new RealSubject();
        
        // 创建动态代理
        Subject proxyInstance = (Subject) Proxy.newProxyInstance(
            realSubject.getClass().getClassLoader(),
            realSubject.getClass().getInterfaces(),
            new ProxyHandler(realSubject)
        );
        
        // 通过代理对象调用方法
        proxyInstance.request();
    }
}

运行结果:

Proxy: Logging before request.
RealSubject: Handling request.
Proxy: Logging after request.

动态代理让我们可以在运行时动态生成代理对象,并且无需手动编写代理类,极大地提高了代码的灵活性和可维护性。

四、代理和核心类的关系

在代理模式中,代理类和核心类(真实类)之间的关系可以总结为以下几点:

  • 解耦:代理类与真实类通过接口解耦,客户端无需直接依赖真实类,可以通过代理类访问真实类的功能。

  • 增强功能:代理类可以在不修改真实类代码的前提下,增强或改变真实类的行为,例如添加日志、事务管理等功能。

  • 控制访问:代理类可以在调用真实类的方法前做一些控制,例如权限检查、延迟加载等。

代理类与核心类的关系可以通过下示进行描述:

Client ---> Proxy ----> RealSubject
         (增强功能)       (实际业务逻辑)

五、静态代理和动态代理的区别

特性静态代理动态代理
实现方式编译时生成代理类运行时动态生成代理类
灵活性代理类与真实类紧耦合更加灵活,不需要手动编写代理类
维护性随着接口增多,代理类也增多代理类由反射生成,维护成本低
使用场景简单场景,代理类较少的场景复杂场景,适用于AOP、事务管理等

六、总结

代理模式在Java中应用广泛,无论是静态代理还是动态代理,都能在不修改真实对象的前提下,增强或控制真实对象的行为。静态代理虽然结构简单,但缺乏灵活性;动态代理则利用反射机制,实现了高度的动态性和灵活性。

通过代理模式,我们可以轻松实现日志、权限、事务等功能,大大提高代码的可扩展性和可维护性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值