Backend Development 9 min read

Implementing a Responsibility Chain Pattern with Spring Boot and MyBatis Plus

The article demonstrates how to build a dynamic Chain of Responsibility in a Spring Boot and MyBatis‑Plus application by defining an abstract handler, implementing concrete @Component beans that modify a shared Lombok‑based context, retrieving them via an ApplicationContext‑aware proxy utility, and invoking them in a client‑specified order through a REST endpoint, while suggesting LiteFlow as a production alternative.

Java Tech Enthusiast
Java Tech Enthusiast
Java Tech Enthusiast
Implementing a Responsibility Chain Pattern with Spring Boot and MyBatis Plus

Background : The project exposes an OpenAPI interface that contains dozens of functional points (parameter validation, configuration checks, data persistence, messaging, etc.). Different downstream clients require different subsets of these functions.

Idea : Split each functional point into an independent component and link them using the Chain of Responsibility pattern. The execution order can be defined dynamically (e.g., stored in a database or passed via a request).

Key Implementation :

Define an abstract class ComponentAbstract.java that provides handlerRequest(Contxt contxt) to measure execution time and delegate to an abstract doHandler(Contxt contxt) method.

Create concrete handlers ( Test1.java , Test2.java , Test3.java , Test4.java ) annotated with @Component("1") , @Component("2") … Each overrides doHandler to modify a shared context.

Shared context class Contxt.java holds fields such as name , age , adrss , userid and is annotated with Lombok’s @Data , @Builder , etc.

Utility AopProxyUtils.java implements ApplicationContextAware to retrieve Spring‑managed beans by name.

Controller LiteFlowController.java exposes /test/chain . It parses the index query parameter (e.g., 2,1,3,4 ), obtains the corresponding beans via AopProxyUtils.getProxyBean(className) , invokes handlerRequest in the specified order, and returns the final Contxt as JSON.

Sample Code Snippets :

public abstract class ComponentAbstract {
    public void handlerRequest(Contxt contxt) {
        // measure execution time
        this.doHandler(contxt);
    }
    public abstract void doHandler(Contxt contxt);
}
@Component("1")
public class Test1 extends ComponentAbstract {
    @Override
    public void doHandler(Contxt contxt) {
        log.info("Test1-顺序1-上下文内容为:{}", JSON.toJSONString(contxt));
        contxt.setName("Test1");
        // other fields set …
    }
}
@Data @Builder @AllArgsConstructor @NoArgsConstructor
public class Contxt {
    private String name;
    private String age;
    private String adrss;
    private String userid;
}
@RestController
@RequestMapping("/test")
public class LiteFlowController {
    @GetMapping("chain")
    public String pattern(@RequestParam String index) {
        Contxt contxt = Contxt.builder()
            .name("初始化").age("初始化").adrss("初始化").userid("初始化").build();
        for (String className : index.split(",")) {
            ComponentAbstract handler = (ComponentAbstract) AopProxyUtils.getProxyBean(className);
            if (handler != null) {
                handler.handlerRequest(contxt);
            }
        }
        return JSON.toJSONString(contxt);
    }
}

Note : While a custom implementation is shown, the author mentions that the LiteFlow framework would be a more suitable choice for production use.

JavaSpring Bootdesign patternMyBatis-Plusresponsibility chainREST API
Java Tech Enthusiast
Written by

Java Tech Enthusiast

Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.