装饰者模式(AOP方式来添加函数职责)

本文介绍了一种在JavaScript中实现面向切面编程(AOP)的方法,通过扩展Function.prototype,可以在函数执行前后添加额外的功能,例如日志记录或权限检查。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通常,在JavaScript中实现AOP(Aspect Oriented Programming,面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。),都是指把一个函数“动态织入”到另一个函数中,具体实现方式有很多,以下是通过扩展Function.prototype来做到者点。

    Function.prototype.before = function( beforefn ) {
      var _self = this  // 保存原函数引用
      return function() { // 返回包含原函数和新函数的“代理”函数
        beforefn.apply( this, arguments ) // 执行新函数,修正this
        return _self.apply( this, arguments ) // 执行原函数
      }
    }

    Function.prototype.after = function( afterfn ) {
      var _self = this
      return function() {
        var ret = _self.apply( this, arguments )
        afterfn.apply( this, arguments )
        return ret
      }
    }

    var func = function() {
      console.log(2)
    }

    func = func.before(function() {
      console.log(1)
    }).after(function() {
      console.log(3)
    })

    func()

 func链式执行before和after,before函数里插入了打印数字1的方法,再连同func方法一起return给after函数执行,所以打印结果是1 2 3,我们把负责打印1和打印3的函数通过AOP的方式动态植入func函数。

 

<think>我们正在寻找Spring框架中应用装饰模式的具体位置,并展示相关类图。根据之前的讨论,我们知道Spring中装饰模式的应用主要体现在: 1. AOP的动态代理 2. 事务管理(如TransactionTemplate) 3. HTTP请求处理(如ClientHttpRequestInterceptor) 4. 以及一些Wrapper类(如HttpHeadResponseDecorator) 现在,我们将深入Spring源码,找出具体应用装饰模式的类,并绘制类图。 根据引用[3],在Spring MVC中有一个`HttpHeadResponseDecorator`类,它继承自`ServerHttpResponseDecorator`,而`ServerHttpResponseDecorator`是一个典型的装饰器。 另外,在Spring的事务管理中,我们也可以看到装饰模式的应用,比如`TransactionInterceptor`(它本质上是一个AOP的Advice,但也可以看作是对目标方法的装饰)。 我们还可以在Spring WebFlux中找到装饰模式的应用,例如`ServerHttpResponseDecorator`。 下面我们分别从几个方面来展示: 1. **Spring Web中的装饰模式:ServerHttpResponseDecorator** 在Spring WebFlux模块中,`org.springframework.http.server.reactive.ServerHttpResponseDecorator`是一个典型的装饰器。 它继承自`ServerHttpResponse`,同时内部持有一个`ServerHttpResponse`的引用(委托对象)。 2. **Spring AOP中的装饰模式:AdvisedSupport** 在AOP中,Spring使用动态代理来创建装饰对象。虽然动态代理是代理模式,但也可以看作是装饰模式的一种实现方式(因为它们都是对原有对象的功能增强,且保持接口一致)。具体来说,`ProxyFactory`创建代理对象,该代理对象包装了目标对象,并添加了拦截器链(即增强逻辑)。 3. **Spring事务管理:TransactionInterceptor** 事务管理也是通过AOP实现的,所以本质上和AOP相同。`TransactionInterceptor`是一个方法拦截器,它包装了目标方法,在方法调用前后添加事务管理逻辑。 4. **Spring MVC中的HandlerInterceptorAdapter** 引用[1]提到`HandlerInterceptorAdapter`,这实际上是适配器模式,但我们可以注意一下,在Spring中也有使用装饰模式的地方,比如`WebContentInterceptor`(它继承自`HandlerInterceptorAdapter`,但这里主要是适配器模式装饰模式并不明显)。所以我们重点放在前面提到的几个地方。 由于类图无法直接在此绘制,我们将使用mermaid语法描述类图,并给出关键类的代码结构。 我们以`ServerHttpResponseDecorator`为例: **类图** (使用mermaid语法): ```mermaid classDiagram direction BT class ServerHttpResponse { <<interface>> +writeWith(Publisher~DataBuffer~) Mono~Void~ +setStatusCode(HttpStatus) // ... 其他方法 } class ServerHttpResponseDecorator { -final ServerHttpResponse delegate +ServerHttpResponseDecorator(ServerHttpResponse delegate) +writeWith(Publisher~DataBuffer~) Mono~Void~ +setStatusCode(HttpStatus) void // ... 其他方法覆盖,通常调用委托对象的方法 } class HttpHeadResponseDecorator { +HttpHeadResponseDecorator(ServerHttpResponse delegate) +writeWith(Publisher~DataBuffer~) Mono~Void~ // ... 覆盖方法,可能改变行为 } ServerHttpResponseDecorator ..|> ServerHttpResponse ServerHttpResponseDecorator o-- ServerHttpResponse : 委托对象 HttpHeadResponseDecorator --|> ServerHttpResponseDecorator ``` **代码结构示例**: ```java // 装饰器基类 public class ServerHttpResponseDecorator implements ServerHttpResponse { private final ServerHttpResponse delegate; public ServerHttpResponseDecorator(ServerHttpResponse delegate) { this.delegate = delegate; } @Override public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) { return this.delegate.writeWith(body); } @Override public void setStatusCode(HttpStatus status) { this.delegate.setStatusCode(status); } // ... 其他方法都委托给delegate } // 具体装饰器 public class HttpHeadResponseDecorator extends ServerHttpResponseDecorator { public HttpHeadResponseDecorator(ServerHttpResponse delegate) { super(delegate); } @Override public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) { // 对于HEAD请求,不写body,所以这里覆盖方法,改变行为 return Mono.empty(); } } ``` 在这个例子中: - `ServerHttpResponse` 是组件接口。 - `ServerHttpResponseDecorator` 是装饰器基类,它持有一个`ServerHttpResponse`类型的委托对象,并实现了`ServerHttpResponse`接口,将方法调用委托给这个对象。 - `HttpHeadResponseDecorator` 是具体装饰器,它覆盖了`writeWith`方法,改变了行为(对于HEAD请求,不写入响应体)。 另一个例子是Spring的`BeanDefinitionDecorator`接口(用于装饰Bean定义),但不如上面的例子典型。 总结一下,在Spring源码中装饰模式的应用位置: - `org.springframework.http.server.reactive.ServerHttpResponseDecorator` (WebFlux) - `org.springframework.http.server.reactive.ServerHttpRequestDecorator` (WebFlux) - `org.springframework.http.server.ServletServerHttpResponse` (Web MVC) 并不是装饰者,但WebFlux中使用了装饰模式。 - 在AOP中,虽然使用了代理模式,但也可以看作装饰模式的一种动态实现。 因此,我们重点展示了WebFlux中的响应装饰器。 注意:Spring Web MVC中也有类似的装饰器,例如`HttpServletRequestWrapper`和`HttpServletResponseWrapper`(来自Servlet API,Spring在其基础上使用),但它们是Java EE的标准类,并不是Spring自己实现的。不过Spring在`org.springframework.web.util`包中也提供了一些装饰器,比如`ContentCachingRequestWrapper`。 我们再看一个Spring自己实现的装饰器例子:`ContentCachingRequestWrapper`(位于`org.springframework.web.util`包中) 类图: ```mermaid classDiagram direction BT class HttpServletRequest { <<interface>> +getInputStream() ServletInputStream +getReader() BufferedReader // ... 其他方法 } class ContentCachingRequestWrapper { -byte[] content -ServletInputStream inputStream -InputStream inputStream +ContentCachingRequestWrapper(HttpServletRequest request) +getInputStream() ServletInputStream +getReader() BufferedReader +getContentAsByteArray() byte[] // ... 它缓存了请求体,以便多次读取 } ContentCachingRequestWrapper ..|> HttpServletRequest ContentCachingRequestWrapper o-- HttpServletRequest : 委托对象 ``` 在这个装饰器中,它包装了原始的`HttpServletRequest`,并重写了`getInputStream`和`getReader`方法,将读取的请求内容缓存起来,这样就可以多次读取请求体(因为原始的请求体只能读取一次)。 所以,在Spring框架中,装饰模式的应用非常广泛,尤其是在需要增强或修改原有对象行为而不改变其接口的情况下。 最后,我们总结一下Spring中装饰模式的应用: - **目的**:动态地给对象添加额外的职责,且不改变其接口。 - **实现方式**:通常通过包装(wrapper)的方式,包装对象实现了与原始对象相同的接口,并持有原始对象的引用,在调用原始对象方法前后可以添加自己的行为。 - **在Spring中的典型应用**: 1. Web请求和响应的包装(如缓存请求体、修改响应行为等)。 2. AOP中的代理对象(虽然动态代理是代理模式,但也可以视为装饰模式)。 3. 事务管理(通过拦截器包装目标方法)。 以上就是在Spring源码中应用装饰模式的具体位置和相关类图的展示。 §§相关问题§§ 1. 装饰模式和代理模式在Spring AOP中的具体区别是什么? 2. 除了Web请求和响应,Spring中还有哪些模块使用了装饰模式? 3. 如何自定义一个装饰器来增强Spring Bean的功能?</think>### Spring源码中装饰模式的具体应用与类图展示 在Spring框架中,装饰模式主要通过**Wrapper类**和**Decorator实现类**来实现功能扩展。以下是源码中的核心应用位置和相关类图: --- #### 1. **HTTP响应装饰器:`ServerHttpResponseDecorator`** **位置**:`org.springframework.http.server.reactive.ServerHttpResponseDecorator` **功能**:为HTTP响应添加额外功能(如修改头信息、拦截响应体等) ```java public class ServerHttpResponseDecorator implements ServerHttpResponse { private final ServerHttpResponse delegate; // 被装饰对象 public ServerHttpResponseDecorator(ServerHttpResponse delegate) { this.delegate = delegate; } // 装饰方法示例:修改响应头 @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); headers.putAll(delegate.getHeaders()); // 原始功能 headers.add("X-Decorated-By", "Spring"); // 新增功能 return headers; } // 其他方法委托给被装饰对象 @Override public <T> T getNativeResponse() { return delegate.getNativeResponse(); } } ``` **类图**: ```mermaid classDiagram direction BT class ServerHttpResponse { <<interface>> +getHeaders() HttpHeaders +getNativeResponse() T } class ServerHttpResponseDecorator { -delegate: ServerHttpResponse +getHeaders() HttpHeaders +getNativeResponse() T } class HttpHeadResponseDecorator { +writeWith(Publisher~DataBuffer~) Mono~Void~ } ServerHttpResponseDecorator ..|> ServerHttpResponse ServerHttpResponseDecorator o--> ServerHttpResponse : 持有引用 HttpHeadResponseDecorator --|> ServerHttpResponseDecorator ``` **关键点**: 1. 实现相同接口 `ServerHttpResponse` 2. 构造函数注入被装饰对象 (`delegate`) 3. 在方法中组合原始功能与新增功能 4. 具体装饰器 `HttpHeadResponseDecorator` 实现特殊行为[^3] --- #### 2. **Bean定义装饰器:`BeanDefinitionDecorator`** **位置**:`org.springframework.beans.factory.xml.BeanDefinitionDecorator` **功能**:动态修改Spring容器的Bean定义 ```java public interface BeanDefinitionDecorator { // 装饰Bean定义的方法 BeanDefinitionHolder decorate( Node node, BeanDefinitionHolder definition, ParserContext parserContext ); } // 具体实现:ScopedProxyBeanDefinitionDecorator public class ScopedProxyBeanDefinitionDecorator implements BeanDefinitionDecorator { @Override public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) { // 1. 创建代理定义(装饰核心逻辑) BeanDefinitionHolder proxyDefinition = ScopedProxyUtils.createScopedProxy(definition, registry); // 2. 保留原始Bean引用 registry.registerBeanDefinition(definition.getBeanName(), definition.getBeanDefinition()); return proxyDefinition; // 返回装饰后的定义 } } ``` **执行流程**: 1. 解析XML配置时遇到自定义标签 2. 调用对应的 `BeanDefinitionDecorator` 3. 基于原始Bean定义创建装饰版本 4. 注册装饰后的Bean到容器 --- #### 3. **AOP中的装饰模式** **位置**:`org.springframework.aop.framework.ProxyFactory` **功能**:通过动态代理实现方法拦截 ```java public class ProxyFactory extends ProxyCreatorSupport { // 创建装饰后的代理对象 public Object getProxy() { return createAopProxy().getProxy(); } // 内部使用装饰器链 protected final synchronized AopProxy createAopProxy() { // 选择JDK动态代理或CGLIB代理 return getAopProxyFactory().createAopProxy(this); } } ``` **类关系**: ```mermaid classDiagram class TargetSource { <<interface>> +getTarget() Object } class AdvisedSupport { -targetSource: TargetSource -advisorChainFactory: AdvisorChainFactory } class ProxyFactory { +getProxy() Object } class JdkDynamicAopProxy { -advised: AdvisedSupport +invoke(Object, Method, Object[]) Object } AdvisedSupport o--> TargetSource ProxyFactory --|> AdvisedSupport JdkDynamicAopProxy o--> AdvisedSupport ``` **实现原理**: 1. `ProxyFactory` 包装原始对象 (`TargetSource`) 2. 通过 `AdvisorChainFactory` 组织拦截器链(装饰逻辑) 3. 代理对象执行方法时按顺序调用拦截器 4. 最终调用原始对象方法[^4] --- ### 装饰模式在Spring中的设计特点 1. **统一接口**: ```mermaid graph LR A[Component接口] --> B[ConcreteComponent] A --> C[Decorator] C --> D[ConcreteDecorator] ``` 2. **透明扩展**: - 装饰器与被装饰对象实现相同接口 - 调用方无需知道是否被装饰 - 支持多层嵌套装饰 3. **Spring实现优势**: - 通过IoC容器自动装配装饰器 - 结合动态代理实现运行时装饰 - 注解驱动(如`@Transactional`本质是装饰器) 这些实现展示了Spring如何通过装饰模式实现**开闭原则**:在不修改原始代码的情况下扩展功能,同时保持核心组件的纯净性[^2][^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值