Implementando aprimoramentos de componentes para o padrão Chain of Responsibility usando anotações personalizadas e @Aspect

modelo de cadeia de responsabilidade

O padrão Chain of Responsibility é um padrão de design comportamental que separa o remetente e o destinatário de solicitações para que as solicitações possam ser organizadas e processadas de forma flexível. Ele funciona passando e processando solicitações ao longo de uma cadeia de processadores até que um processador seja capaz de lidar com a solicitação ou o fim da cadeia.

As principais funções deste modo são:

  1. Desacoplamento do remetente e do destinatário da solicitação: o modo de cadeia de responsabilidade dissocia o remetente e o destinatário. O remetente não precisa saber qual destinatário está lidando com a solicitação e o destinatário não precisa saber quem é o remetente da solicitação, melhorando assim o sistema eficiência Flexibilidade e facilidade de manutenção.

  2. Organizar e processar solicitações dinamicamente: o modelo Chain of Responsibility pode organizar e processar solicitações dinamicamente, ajustar de forma flexível a ordem e o número de processadores no link de acordo com as condições reais e implementar diferentes lógicas de negócios e estratégias de processamento.

  3. Evite a codificação permanente de solicitações: o padrão Chain of Responsibility lida com solicitações por meio de configuração e links, evitando a codificação permanente de solicitações e tornando o sistema mais fácil de expandir e manter.

Cenário de aplicação:

  1. O processamento da solicitação envolve vários links ou vários objetos: Quando uma solicitação precisa ser processada por vários links de processamento ou vários objetos, o padrão de cadeia de responsabilidade pode ser usado. Por exemplo, o processamento de solicitações precisa ser processado por vários processadores, como autenticação, log e cache.

  2. Seleção dinâmica de processadores: Quando a seleção e a ordem dos processadores precisam ser ajustadas dinamicamente de acordo com a situação real, o padrão Chain of Responsibility pode ser usado. Por exemplo, selecione dinamicamente um processador com base no tipo ou prioridade da solicitação.

  3. Cenários em que as solicitações precisam ser filtradas ou interceptadas: Quando as solicitações precisam ser filtradas, interceptadas ou processadas de acordo com as condições, o padrão Cadeia de Responsabilidade pode ser usado. Por exemplo, operações como verificação de permissão, verificação de segurança e verificação de dados são executadas na solicitação.

  4. Reduza o acoplamento e melhore a flexibilidade e a manutenibilidade do sistema: quando for necessário reduzir o acoplamento entre o emissor e o receptor e melhorar a flexibilidade e a manutenibilidade do sistema, o padrão da cadeia de responsabilidade pode ser considerado.

Resumindo, o padrão Chain of Responsibility é adequado para cenários em que a cadeia de solicitação de processamento é longa, os processadores são fracamente acoplados e as solicitações precisam ser organizadas e processadas dinamicamente. Ele pode nos ajudar a obter um design de sistema mais flexível, escalável e sustentável.

caso prático

Combinado com anotações personalizadas e @Aspect, podemos aprimorar o componente para ter a função do modo de cadeia de responsabilidade.

Primeiro, precisamos definir uma anotação personalizada para identificar o método ou classe que precisa aplicar o padrão Chain of Responsibility. As seguintes anotações podem ser definidas:

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

おすすめ

転載: juejin.im/post/7234923935599001656