使用自定义注解和@Aspect实现责任链模式的组件增强

1,449 阅读6分钟

责任链模式

责任链模式是一种行为设计模式,其作用是将请求的发送者和接收者解耦,从而可以灵活地组织和处理请求。它通过将请求沿着一个由多个处理器组成的链路进行传递和处理,直到有一个处理器能够处理该请求或者链路的末端。

该模式的主要作用是:

  1. 解耦请求发送者和接收者:责任链模式将发送者和接收者解耦,发送者无需知道具体是哪个接收者来处理请求,接收者也无需知道请求的发送者是谁,从而提高系统的灵活性和可维护性。

  2. 动态组织和处理请求:责任链模式可以动态地组织和处理请求,可以根据实际情况灵活地调整链路上的处理器顺序和数量,实现不同的业务逻辑和处理策略。

  3. 避免请求的硬编码:责任链模式通过配置和链路的方式来处理请求,避免了请求的硬编码,使得系统更易于扩展和维护。

应用场景:

  1. 请求的处理涉及多个环节或多个对象:当一个请求需要经过多个处理环节或者多个对象来处理时,可以使用责任链模式。例如,请求的处理需要经过验证、日志记录、缓存等多个处理器进行处理。

  2. 动态选择处理器:当处理器的选择和顺序需要根据实际情况进行动态调整时,可以使用责任链模式。例如,根据请求的类型或者优先级来动态选择处理器。

  3. 需要对请求进行过滤或拦截的场景:当需要对请求进行过滤、拦截或者根据条件决定是否进行处理时,可以使用责任链模式。例如,对请求进行权限验证、安全检查、数据校验等操作。

  4. 减少耦合,提高系统的灵活性和可维护性:当需要降低发送者和接收者之间的耦合度,以及提高系统的灵活性和可维护性时,可以考虑使用责任链模式。

总之,责任链模式适用于处理请求链路较长、处理器之间松耦合、需要动态组织和处理请求的场景。它可以帮助我们实现更灵活、可扩展和可维护的系统设计。

实践案例

下面结合自定义注解和@Aspect,我们可以实现对组件的增强,使其具备责任链模式的功能。

首先,我们需要定义一个自定义注解,用于标识需要应用责任链模式的方法或类。可以定义如下注解:

package com.example.demo.design.chain;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyChain {}

接下来,我们使用@Aspect注解创建一个切面类,在切面类中实现责任链模式的逻辑。可以定义如下切面类

package com.example.demo.design.chain;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.List;

@Aspect
@Component
public class ChainHandlerAspect implements InitializingBean {
    @Autowired
    // 注入所有实现ChainHandler接口的责任链处理器
    private List<ChainHandler> chainHandlers;

    // 责任链的头节点
    private ChainHandler chainHandler;

    @Around("@annotation(com.example.demo.design.chain.MyChain)")
    public Object checkParam(ProceedingJoinPoint pjp) throws Throwable {
        Object[] args = pjp.getArgs(); // 获取方法的所有参数
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        Class<?>[] parameterTypes = method.getParameterTypes(); // 获取方法的参数类型列表

        for (int i = 0; i < parameterTypes.length; i++) {
            if (parameterTypes[i].getName().equals("java.lang.String")) {
                chainHandler.handle(new Request((String) args[0]));
            }
        }
        return pjp.proceed();
    }

    /**
     * 构建处理器链
     */
    private ChainHandler buildHandlerChain() {
        ChainHandler headChainHandler = null;
        ChainHandler currentChainHandler = null;
        for (ChainHandler chainHandler : chainHandlers) {
            if (headChainHandler == null) {
                headChainHandler = chainHandler;
                currentChainHandler = headChainHandler;
            } else {
                currentChainHandler.setNextHandler(chainHandler);
                currentChainHandler = chainHandler;
            }
        }
        return headChainHandler;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // 构建责任链
        chainHandler = this.buildHandlerChain();
    }
}

责任链相关组件

处理器接口

package com.example.demo.design.chain;

public interface ChainHandler {
    void handle(Request request);

    void setNextHandler(ChainHandler handler);
}

处理器实现类

package com.example.demo.design.chain;

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Order(1)
public class FirstHandler implements ChainHandler {
    private ChainHandler nextHandler;

    @Override
    public void handle(Request request) {
        // 处理请求
        System.out.println("FirstHandler handling request " + request);

        // 将请求传递给下一个处理器
        if (nextHandler != null) {
            nextHandler.handle(request);
        }
    }

    @Override
    public void setNextHandler(ChainHandler handler) {
        this.nextHandler = handler;
    }
}
package com.example.demo.design.chain;

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Order(2)
public class SecondHandler implements ChainHandler {
    private ChainHandler nextHandler;

    @Override
    public void handle(Request request) {
        // 处理请求
        System.out.println("SecondHandler handling request " + request);

        // 将请求传递给下一个处理器
        if (nextHandler != null) {
            nextHandler.handle(request);
        }
    }

    @Override
    public void setNextHandler(ChainHandler handler) {
        this.nextHandler = handler;
    }
}
package com.example.demo.design.chain;

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Order(3)
public class ThirdHandler implements ChainHandler {
    private ChainHandler nextHandler;

    @Override
    public void handle(Request request) {
        // 处理请求
        System.out.println("ThirdHandler handling request " + request);
    }

    @Override
    public void setNextHandler(ChainHandler handler) {
        this.nextHandler = handler;
    }
}

以上代码是类同的,通过@Order注解指定了处理器的执行顺序,数字越小,优先级越高。

setNextHandler方法用于设置下一个处理器,接收一个ChainHandler对象作为参数,并将其保存在nextHandler字段中。

Request类

package com.example.demo.design.chain;

public class Request {
    private String data;

    public Request(String data) {
        this.data = data;
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "Request{" +
                "data='" + data + ''' +
                '}';
    }
}

业务代码组件

package com.example.demo.design.chain;

import org.springframework.stereotype.Component;

@Component
public class BizComponent {
    @MyChain
    public void process(String data) {
        System.out.println(data);
    }
}

@MyChain注解用于标记需要应用责任链模式的方法或类。

启动类

package com.example.demo.design.chain;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(com.example.demo.design.chain.Application.class, args);
    }
}

@EnableAspectJAutoProxy注解用于启用AspectJ自动代理功能,使得Spring能够识别和应用切面。

package com.example.demo.design.chain;

import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
@Data
public class ComponentRunner implements CommandLineRunner {

    @Autowired
    private BizComponent bizComponent;

    @Override
    public void run(String... args) throws Exception {
        // 执行某个方法(带Chain注解)
        bizComponent.process("Hello world!");
    }
}

该组件类的执行逻辑是在应用程序启动后自动执行的,可以根据实际需求,在run方法中编写适当的业务逻辑和处理流程。

主要是为了模拟发起请求,可以使用Controller访问的方式。

**执行效果 **

图片

我们可以看到,在执行bizComponent.process("Hello world!")之前,我们已经被注解@MyChain进行增强处理了,所以会经过责任链进行前置处理。

总结

通过这种方式,我们可以灵活地扩展和定制责任链的处理逻辑,通过注解和AOP的方式将责任链与业务组件进行解耦,实现组件的增强和复用。

责任链模式的应用场景很广泛,例如在Web开发中,可以使用责任链模式来处理请求的拦截、验证、日志记录等操作;在工作流引擎中,可以使用责任链模式来实现任务的处理和流转;在事件驱动系统中,可以使用责任链模式来处理事件的触发和传递等等。

通过结合自定义注解和Spring的AOP功能,我们可以更加方便地应用责任链模式,并在开发过程中获得更高的可扩展性和灵活性。这种组件增强的方式使得责任链模式的实现更加简洁、可读性更高,同时也提升了代码的可维护性和可测试性。

总而言之,使用自定义注解和@Aspect实现责任链模式的组件增强,是一种强大的编程技巧,能够有效地将责任链的逻辑与业务组件解耦,提供了一种灵活且可扩展的方式来处理请求和逻辑链的处理。这种结合注解和AOP的方式,使得责任链模式的应用更加简单、优雅,为我们的开发工作带来了便利和效益。

欢迎关注公众号:程序员的思考与落地

公众号提供大量实践案例,Java入门者不容错过哦,可以交流!!