Implementación de mejoras de componentes para el patrón Cadena de responsabilidad utilizando anotaciones personalizadas y @Aspect

modelo de cadena de responsabilidad

El patrón de cadena de responsabilidad es un patrón de diseño de comportamiento que desvincula al remitente y al receptor de las solicitudes para que las solicitudes se puedan organizar y procesar de manera flexible. Funciona pasando y procesando solicitudes a lo largo de una cadena de procesadores hasta que un procesador puede manejar la solicitud o el final de la cadena.

Las principales funciones de este modo son:

  1. Desacoplamiento del remitente y el receptor de la solicitud: el modo de cadena de responsabilidad desacopla el remitente y el receptor. El remitente no necesita saber qué receptor está manejando la solicitud, y el receptor no necesita saber quién es el remitente de la solicitud, mejorando así el sistema. eficiencia Flexibilidad y mantenibilidad.

  2. Organizar y procesar solicitudes dinámicamente: el modelo de cadena de responsabilidad puede organizar y procesar solicitudes dinámicamente, ajustar de manera flexible el orden y la cantidad de procesadores en el enlace de acuerdo con las condiciones reales e implementar diferentes estrategias de procesamiento y lógica comercial.

  3. Evite la codificación rígida de las solicitudes: el patrón Cadena de responsabilidad maneja las solicitudes a través de la configuración y los enlaces, evitando la codificación rígida de las solicitudes y facilitando la expansión y el mantenimiento del sistema.

Escenario de aplicación:

  1. El procesamiento de la solicitud involucra múltiples enlaces o múltiples objetos: cuando una solicitud debe ser procesada por múltiples enlaces de procesamiento o múltiples objetos, se puede usar el patrón de cadena de responsabilidad. Por ejemplo, el procesamiento de solicitudes debe ser procesado por varios procesadores, como la autenticación, el registro y el almacenamiento en caché.

  2. Selección dinámica de procesadores: cuando la selección y el orden de los procesadores deben ajustarse dinámicamente de acuerdo con la situación real, se puede utilizar el patrón Cadena de responsabilidad. Por ejemplo, seleccione dinámicamente un procesador según el tipo o la prioridad de la solicitud.

  3. Escenarios en los que es necesario filtrar o interceptar las solicitudes: cuando es necesario filtrar, interceptar o procesar las solicitudes según las condiciones, se puede utilizar el patrón Cadena de responsabilidad. Por ejemplo, en la solicitud se realizan operaciones como la verificación de permisos, la verificación de seguridad y la verificación de datos.

  4. Reducir el acoplamiento y mejorar la flexibilidad y mantenibilidad del sistema: cuando es necesario reducir el acoplamiento entre el emisor y el receptor y mejorar la flexibilidad y mantenibilidad del sistema, se puede considerar el patrón de cadena de responsabilidad.

En resumen, el patrón Cadena de responsabilidad es adecuado para escenarios en los que la cadena de solicitudes de procesamiento es larga, los procesadores están poco acoplados y las solicitudes deben organizarse y procesarse dinámicamente. Puede ayudarnos a lograr un diseño de sistema más flexible, escalable y mantenible.

Caso de práctica

Combinado con anotaciones personalizadas y @Aspect, podemos mejorar el componente para que tenga la función del modo de cadena de responsabilidad.

Primero, necesitamos definir una anotación personalizada para identificar el método o la clase que necesita aplicar el patrón Cadena de responsabilidad. Se pueden definir las siguientes anotaciones:

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入门者不容错过哦,可以交流!!

Supongo que te gusta

Origin juejin.im/post/7234923935599001656
Recomendado
Clasificación