使用自定义注解和@Aspect实现责任链模式的组件增强
责任链模式
责任链模式是一种行为设计模式,其作用是将请求的发送者和接收者解耦,从而可以灵活地组织和处理请求。它通过将请求沿着一个由多个处理器组成的链路进行传递和处理,直到有一个处理器能够处理该请求或者链路的末端。
该模式的主要作用是:
-
解耦请求发送者和接收者:责任链模式将发送者和接收者解耦,发送者无需知道具体是哪个接收者来处理请求,接收者也无需知道请求的发送者是谁,从而提高系统的灵活性和可维护性。
-
动态组织和处理请求:责任链模式可以动态地组织和处理请求,可以根据实际情况灵活地调整链路上的处理器顺序和数量,实现不同的业务逻辑和处理策略。
-
避免请求的硬编码:责任链模式通过配置和链路的方式来处理请求,避免了请求的硬编码,使得系统更易于扩展和维护。
应用场景:
-
请求的处理涉及多个环节或多个对象:当一个请求需要经过多个处理环节或者多个对象来处理时,可以使用责任链模式。例如,请求的处理需要经过验证、日志记录、缓存等多个处理器进行处理。
-
动态选择处理器:当处理器的选择和顺序需要根据实际情况进行动态调整时,可以使用责任链模式。例如,根据请求的类型或者优先级来动态选择处理器。
-
需要对请求进行过滤或拦截的场景:当需要对请求进行过滤、拦截或者根据条件决定是否进行处理时,可以使用责任链模式。例如,对请求进行权限验证、安全检查、数据校验等操作。
-
减少耦合,提高系统的灵活性和可维护性:当需要降低发送者和接收者之间的耦合度,以及提高系统的灵活性和可维护性时,可以考虑使用责任链模式。
总之,责任链模式适用于处理请求链路较长、处理器之间松耦合、需要动态组织和处理请求的场景。它可以帮助我们实现更灵活、可扩展和可维护的系统设计。
实践案例
下面结合自定义注解和@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入门者不容错过哦,可以交流!!
转载自:https://juejin.cn/post/7234923935599001656