An Annotation for Chain of Responsibility

Introduction: As a common design pattern, Chain of Responsibility is a powerful tool for business process decoupling. But writing a chain of responsibility by hand is time-consuming and laborious. Is there a shortcut, as simple as lombok? Yes, it's foldright/auto-pipeline, and it's easy to do with one annotation!


In the tedious business process processing, the process-oriented design method is usually used to split the process into N steps, and each step executes independent logic.

However, such stripping is still incomplete, and modifying one of the steps may still affect other steps (modification of the same class does not conform to the open-closed principle). In this scenario, there is a classic design pattern - the Chain of Responsibility pattern, which can encapsulate these sub-steps into independent handlers, and then chain them together through a pipeline.

In general, pure manual writing has the following problems:

• Correctness: The implementation complexity is high, and manual writing in a short time is prone to errors
• Development efficiency: Involving the implementation of multiple classes, it takes a lot of time to test the non-business pipeline process, and the ROI is not high
• Reusability: It is difficult for different business processes to reuse the key code of the same pipeline
Is there a reliable framework that can solve the above problems? Yes, it's foldright/auto-pipeline, the "lombok" of Chain of Responsibility!

Quirk Start

The following takes reading the system configuration as an example. The reading logic is as follows:
• Read from the local configuration file, return directly if the read is successful, otherwise go to the next step
• Read from system variable and return the corresponding value

Implementation principle

The business interface is implemented through the generated Pipeline structure, and the Pipeline is responsible for assembling the responsibility chain and calling the first node (head) of the linked list. If the first node has a return value after processing, it will return directly; otherwise, it will be passed to the next node. If the processing to the last node (tail) is still empty, return empty directly.

• User implementation:
• ConfigSource
• User-defined interface for obtaining configuration
• Handler implementation:
• MapConfigSourceHandler, SystemConfigSourceHandler
• AutoPipeline generation
• ConfigSourcePipeline
• Meaning: Chain of Responsibility Pipeline
• Core role: concatenate ConfigSourceHandler into a linked list
• ConfigSourceHandlerContext
• Meaning: The context of Handler, compared with the traditional chain of responsibility, adds the ability to obtain the global Pipeline
• AbstractConfigSourceHandlerContext
• Meaning: abstract class for Handler's context
• Data structure: mainly consists of three parts: pre, next, handler
• Core function: Implement String get(String key) method through handler().get(key , findNextCtx())
• DefaultConfigSourceHandlerContext
• The default implementation class that holds the ConfigSourceHandler object

Generation principle

Register the compile-time annotation @AutoPipelineProcessor through SPI, and generate business pipeline source code through the javapoet framework during the compilation process.

Register compile-time annotations
• Write annotation class: AutoPipelineProcessor
• Inherit JDK's AbstractProcessor and implement the process method
• Create a new folder under the resources directory: META-INF/services
• Add a new spi file in META-INF/services: javax.annotation.processing.Processor, file writing needs to inherit the full class name of AbstractProcessor
Related class introduction:
• Processor
• Provides annotation processing, which is extended according to the SPI specification
• AbstractProcessor
• The annotation processor mainly extends the processing class
Generate source code
JDK terminology introduction:
• ProcessingEnvironment
• Collection of annotation processing tools
• Element
• is an interface that represents a program element, which can be a package, class, method, or a variable
• PackageElement
• Represents a package program element that provides access to information about the package and its members.
• ExecutableElement
• Represents a method, constructor, or initializer (static or instance) of a class or interface, including annotation type elements.
• TypeElement
• Represents a class or interface program element that provides access to information about the type and its members. Note that an enumeration type is a class, and an annotation type is an interface.
• VariableElement
• Represents a field, enum constant, method or constructor parameter, local variable or exception parameter.
• Filer
• File manager, mainly responsible for generating source code, class or auxiliary files
Introduction to JavaPoet technology:
• TypeSpec
• Tools for generating classes, interfaces, enumerations
• MethodSpec
• Utility class for generating constructors or normal methods

Related Articles

Explore More Special Offers

  1. Short Message Service(SMS) & Mail Service

    50,000 email package starts as low as USD 1.99, 120 short messages start at only USD 1.00

phone Contact Us