设计模式中的代理模式

在Java中,代理模式(Proxy Pattern)可以通过静态代理和动态代理两种主要方式实现。

一、静态代理模式

在编译时就已经确定了代理类和被代理类的关系。

代理类和目标对象通常实现相同的接口或继承相同父类。

缺点是对于每个需要代理的目标对象都需要创建一个代理类,这会导致代码膨胀。

复制代码
interface Service {
    void performAction();
}
 
class RealService implements Service {
    @Override
    public void performAction() {
        System.out.println("Performing action in RealService.");
    }
}
 
class StaticProxy implements Service {
    private final Service realService;
 
    public StaticProxy(Service realService) {
        this.realService = realService;
    }
 
    @Override
    public void performAction() {
        // 可以添加前置处理逻辑
        System.out.println("Before performing action.");
        realService.performAction();
        // 可以添加后置处理逻辑
        System.out.println("After performing action.");
    }
}

二、动态代理模式

动态代理允许我们在运行时创建代理对象,而不需要为每一个委托类都编写一个具体的代理类。这提供了更高的灵活性和可扩展性。Java中的动态代理主要分为两种:基于接口的代理和基于子类的代理。

  1. JDK动态代理

使用java.lang.reflect.Proxy类结合InvocationHandler接口,在运行时动态生成代理对象。

只适用于实现了接口的类。

这种方式允许在不修改原代码的情况下为多个接口方法添加通用的行为。

java 复制代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
public class DynamicProxyExample {
 
    public static void main(String[] args) {
        Service realService = new RealService();
        Service proxyInstance = (Service) Proxy.newProxyInstance(
                realService.getClass().getClassLoader(),
                realService.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("Before " + method.getName());
                        Object result = method.invoke(realService, args);
                        System.out.println("After " + method.getName());
                        return result;
                    }
                });
        proxyInstance.performAction();
    }
}
  1. CGLIB 动态代理

当目标对象没有实现任何接口时,可以使用CGLIB库通过继承的方式生成代理类。

CGLIB会在运行时生成目标类的一个子类,并重写其中的方法以插入自定义逻辑。

注意:由于CGLIB是通过继承实现的,因此不能用于代理final类或方法。

使用CGLIB需要引入相应的依赖(如Maven依赖)。

java 复制代码
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
 
import java.lang.reflect.Method;
 
public class CglibProxyExample {
 
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(RealService.class);
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                System.out.println("Before " + method.getName());
                Object result = proxy.invokeSuper(obj, args);
                System.out.println("After " + method.getName());
                return result;
            }
        });
 
        Service service = (Service) enhancer.create();
        service.performAction();
    }
相关推荐
软考真题app12 小时前
软件设计师考试结构型设计模式考点全解析
设计模式·软件设计师·结构型设计模式·考试考点
xiaolin033317 小时前
【设计模式】- 行为型模式1
设计模式·状态模式·责任链模式·策略模式·命令模式·模板方法模式·行为型模式
沐土Arvin18 小时前
深入理解 requestIdleCallback:浏览器空闲时段的性能优化利器
开发语言·前端·javascript·设计模式·html
bao_lanlan19 小时前
兰亭妙微:用系统化思维重构智能座舱 UI 体验
ui·设计模式·信息可视化·人机交互·交互·ux·外观模式
总是难免20 小时前
设计模式 - 单例模式 - Tips
java·单例模式·设计模式
Java致死1 天前
设计模式Java
java·开发语言·设计模式
ghost1432 天前
C#学习第23天:面向对象设计模式
开发语言·学习·设计模式·c#
敲代码的 蜡笔小新2 天前
【行为型之迭代器模式】游戏开发实战——Unity高效集合遍历与场景管理的架构精髓
unity·设计模式·c#·迭代器模式
敲代码的 蜡笔小新3 天前
【行为型之命令模式】游戏开发实战——Unity可撤销系统与高级输入管理的架构秘钥
unity·设计模式·架构·命令模式
m0_555762903 天前
D-Pointer(Pimpl)设计模式(指向实现的指针)
设计模式