How to Streamline Contract Signing Using Strategy, Chain‑of‑Responsibility, and Annotations

This article walks through a Java Spring‑Boot implementation of a contract‑signing workflow, explains the original chain‑of‑responsibility design, shows its limitations, and demonstrates how to replace manual bean wiring with a strategy‑based annotation and enum configuration for flexible node management.

Architect
Architect
Architect
How to Streamline Contract Signing Using Strategy, Chain‑of‑Responsibility, and Annotations

Background

The contract‑signing system originally follows a Chain‑of‑Responsibility (CoR) pattern. Each processing step is a node that receives the output of the previous node and passes its result to the next. The workflow consists of eight logical steps: contract text initialization, contract generation, shield handling, MQ sending, flow update, file upload, channel selection, and the actual channel invocation.

Original CoR Implementation

The project resides under DesignPatterns/src/main/java/com.xbhog.chainresponsibility. It defines request/response POJOs, a Processor interface, and a series of interceptor implementations such as ContractSignCompactInitImpl, ContractSignGenerateImpl, etc.

public class ContractRequest { private String name; private String age; private String status; }
public class ContractResponse { private String status; private String mas; }
ContractSignProcessor

manually injects each interceptor bean and builds a list:

List<Interceptor<T, ContractResponse>> interceptorList = new ArrayList<>();
interceptorList.add(contractCompactInitImpl);
interceptorList.add(contractGenerateImpl);
// ... other beans ...
return new ContractCall(paramter, interceptorList).exectue();
ContractCall

creates a ContractChain that recursively invokes interceptor.process(nextChain) until the last node is reached.

Problems with Manual Wiring

Adding or removing a node requires both a bean injection field change and a list‑construction modification, which is error‑prone and hampers extensibility.

Strategy‑Based Refactoring

To automate bean registration, a custom annotation @ContractSign, an enum ContractSignEnum.SignChannel, and a configuration class SignConfig are introduced. SignConfig scans the Spring application context for beans annotated with @ContractSign and stores them in a ConcurrentHashMap<Integer, Interceptor> keyed by the enum code.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ContractSign { ContractSignEnum.SignChannel SIGN_CHANNEL(); }
public class ContractSignEnum {
    public enum SignChannel {
        SIGN_INIT(1, "合同文本初始化"),
        SIGN_GENERATE(2, "合同文本生成"),
        SIGN_MOCK(3, "签章挡板"),
        SIGN_MQ(4, "合同签章发送MQ"),
        SIGN_TABLE(5, "合同签章表处理"),
        SIGN_UPLOAD(6, "合同签章上传服务器"),
        SIGN_TRADE(7, "签章渠道实际调用");
        private Integer code; private String info;
        SignChannel(Integer code, String info) { this.code = code; this.info = info; }
        public Integer getCode() { return code; }
        public String getInfo() { return info; }
    }
}
public class SignConfig {
    @Resource protected List<Interceptor> contractSignList;
    protected static final Map<Integer, Interceptor> CONTRACT_SIGN_MAP = new ConcurrentHashMap<>();
    @PostConstruct
    public void init() {
        contractSignList.forEach(interceptor -> {
            ContractSign sign = AnnotationUtils.findAnnotation(interceptor.getClass(), ContractSign.class);
            if (sign != null) {
                CONTRACT_SIGN_MAP.put(sign.SIGN_CHANNEL().getCode(), interceptor);
            }
        });
    }
}

Each interceptor implementation is now annotated, for example:

@ContractSign(SIGN_CHANNEL = ContractSignEnum.SignChannel.SIGN_INIT)
@Component
public class ContractSignCompactInitImpl<T extends ContractRequest> implements Interceptor<T, ContractResponse> {
    @Override
    public ContractResponse process(Chain<T, ContractResponse> chain) {
        log.info("=============执行合同文本初始化拦截器开始");
        T request = chain.request();
        request.setStatus("1");
        ContractResponse response = chain.proceed(request);
        return response != null ? response : ContractResponse.builder().status("fail").mas("处理失败").build();
    }
}

The processor now extends SignConfig and builds the interceptor list by iterating over the sorted map keys, eliminating manual ordering:

public class ContractSignProcessor<T extends ContractRequest> extends SignConfig implements Processor<T, ContractResponse> {
    @Override
    public ContractResponse process(T paramter) {
        List<Interceptor<T, ContractResponse>> interceptorList = new ArrayList<>();
        for (Integer key : CONTRACT_SIGN_MAP.keySet()) {
            interceptorList.add(CONTRACT_SIGN_MAP.get(key));
        }
        log.info("签章开始");
        return new ContractCall(paramter, interceptorList).exectue();
    }
}

Result

With the annotation‑driven strategy, adding a new processing node only requires creating the implementation class and annotating it with the appropriate SIGN_CHANNEL. The framework automatically registers the bean and inserts it into the correct position based on the enum order, making the contract‑signing pipeline more maintainable and extensible.

Key Resources

GitHub repository: https://github.com/xbhog/DesignPatternsStudy

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Chain of ResponsibilityDesign PatternsJavaStrategy PatternSpring BootannotationsContract Signing
Architect
Written by

Architect

Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.

0 followers
Reader feedback

How this landed with the community

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.