java自定义注解整合策略模式

java自定义注解整合策略模式

需求:根据用户提交答案自动评分

用户提交答案后,系统需要根据当前应用的配置,自动选择对应的评分策略,并返回评分结果。
请添加图片描述

自定义注解类

package com.bingli.duskeval.scoring;
import org.springframework.stereotype.Component;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE) //指定注解可以加在哪里
@Retention(RetentionPolicy.RUNTIME)  //注解保留
@Component
public @interface ScoringStrategyConfig {

    /**
     * 应用类型(0-得分类应用,1-测评类应用)
     * @return
     */
    int appType();

    /**
     * 分数策略(0-传统算法,1-AI自动评分)
     * @return
     */
    int scoringStrategy();
}

注解解析

@Target 用来指定:这个注解可以加在哪里

@Target(ElementType.TYPE) 表示这个注解只能加在: 类、接口、枚举、注解

ElementType.TYPE        // 类、接口、枚举、注解
ElementType.METHOD      // 方法
ElementType.FIELD       // 成员变量
ElementType.PARAMETER   // 参数
ElementType.CONSTRUCTOR // 构造方法

@Retention 用来指定:这个注解保留到什么时候

@Retention(RetentionPolicy.RUNTIME) 表示程序运行时可以通过反射读取到这个注解

RetentionPolicy.SOURCE   // 只在源码中存在,编译后就没了
RetentionPolicy.CLASS    // 编译后保留在 .class 文件中,但运行时读不到
RetentionPolicy.RUNTIME  // 运行时还存在,可以通过反射读取

@interface 是用来定义注解的。

public @interface ScoringStrategyConfig {   //这样就定义了一个注解
}

@Component 是 Spring 的组件注解,表示被标记的类会交给 Spring 容器管理

@Documented 注解会出现在 JavaDoc 文档中

@Inherited 注解可以被子类继承,只对类有效

策略接口

package com.bingli.duskeval.scoring;
import com.bingli.duskeval.model.entity.App;
import com.bingli.duskeval.model.entity.UserAnswer;
import java.util.List;

public interface ScoringStrategy {

    /**
     * 计算分数
     * @param choices
     * @param app
     * @return
     */
    UserAnswer doScore(List<String> choices, App  app)throws Exception;
}

具体评分策略类

加入前面的自定义注解@ScoringStrategyConfig

package com.bingli.duskeval.scoring;
import org.springframework.stereotype.Component;

/**
 * 自定义得分类评分策略1
 */
@ScoringStrategyConfig(appType = 0, scoringStrategy = 0)
@Component
public class CustomScoreScoringStrategy implements ScoringStrategy {

    @Override
    public UserAnswer doScore(List<String> choices, App app) throws Exception {
        // 具体评分逻辑省略
        return null;
    }
}
package com.bingli.duskeval.scoring;

import org.springframework.stereotype.Component;

/**
 * 自定义得分类评分策略2
 */
@ScoringStrategyConfig(appType = 1, scoringStrategy = 1)
@Component
public class AITestScoringStrategy implements ScoringStrategy {

    @Override
    public UserAnswer doScore(List<String> choices, App app) throws Exception {
        // 具体评分逻辑省略
        return null;
    }
}

策略执行器

package com.bingli.duskeval.scoring;
import com.bingli.duskeval.common.ErrorCode;
import com.bingli.duskeval.exception.BusinessException;
import com.bingli.duskeval.model.entity.App;
import com.bingli.duskeval.model.entity.UserAnswer;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

@Service
public class ScoringStrategyExecutor {

    // 策略列表
    @Resource
    private List<ScoringStrategy> scoringStrategyList;

    /**
     * 评分
     *
     * @param choiceList
     * @param app
     * @return
     * @throws Exception
     */
    public UserAnswer doScore(List<String> choiceList, App app) throws Exception {
        Integer appType = app.getAppType();
        Integer appScoringStrategy = app.getScoringStrategy();
        if (appType == null || appScoringStrategy == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "应用配置有误,未找到匹配的策略");
        }
        // 根据注解获取策略
        for (ScoringStrategy strategy : scoringStrategyList) {
            if (strategy.getClass().isAnnotationPresent(ScoringStrategyConfig.class)) {
                ScoringStrategyConfig scoringStrategyConfig = strategy.getClass().getAnnotation(ScoringStrategyConfig.class);
                if (scoringStrategyConfig.appType() == appType && scoringStrategyConfig.scoringStrategy() == appScoringStrategy) {
                    return strategy.doScore(choiceList, app);
                }
            }
        }
        throw new BusinessException(ErrorCode.SYSTEM_ERROR, "应用配置有误,未找到匹配的策略");
    }
}

调用方

调用方一般是 Controller 或 Service。它不直接调用具体的评分策略类,而是调用策略执行器:

scoringStrategyExecutor.doScore(choiceList, app);

@RestController
@RequestMapping("/score")
public class ScoringController {

    @Resource
    private ScoringStrategyExecutor scoringStrategyExecutor;

    @Resource
    private AppService appService;

    @PostMapping("/do")
    public UserAnswer doScore(@RequestParam Long appId,
                              @RequestBody List<String> choiceList) throws Exception {

        App app = appService.getById(appId);

        return scoringStrategyExecutor.doScore(choiceList, app);
    }
}
posted @ 2026-05-10 18:31  冰黎526  阅读(1)  评论(0)    收藏  举报