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);
}
}

浙公网安备 33010602011771号