废话少说,上代码
定义注解:
[Java] 纯文本查看 复制代码 package com.jichangxiu.server.common.core.annotation;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
/**
* Handler:
*
* [url=home.php?mod=space&uid=686208]@AuThor[/url] Jcx
* [url=home.php?mod=space&uid=441028]@Since[/url] 2025-01-01 00:00:00
*/
@Component
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public [url=home.php?mod=space&uid=593715]@interface[/url] Handler {
@AliasFor(annotation = Component.class)
String value() default "";
}
业务枚举继承接口
[Java] 纯文本查看 复制代码 package com.jichangxiu.server.common.core.strategy;
/**
* Strategy:
*
* @author Jcx
* @since 2025-01-01 00:00:00
*/
public interface Strategy<PARAMETER, RESULT> {
}
业务执行器接口:
[Java] 纯文本查看 复制代码 package com.jichangxiu.server.common.core.strategy;
public interface Executor<PARAMETER, RESULT> {
Strategy<PARAMETER, RESULT> strategy();
RESULT execute(PARAMETER parameter);
}
工厂调度器:
[Java] 纯文本查看 复制代码 package com.jichangxiu.server.common.core.factory;
import com.jichangxiu.server.common.core.strategy.Strategy;
import com.jichangxiu.server.common.core.strategy.Executor;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
/**
* StrategyFactory:
*
* @author Jcx
* @since 2025-01-01 00:00:00
*/
public class StrategyFactory {
private static final Map<Strategy<?, ?>, Executor<?, ?>> STRATEGY_MAP = new ConcurrentHashMap<>();
/**
* 私有构造函数
*/
private StrategyFactory() {
}
/**
* 注册策略
*
* @Param strategy 策略码
* @param executor 策略
*/
public static void register(Strategy<?, ?> strategy, Executor<?, ?> executor) {
Objects.requireNonNull(strategy, "Strategy 不能为空");
Objects.requireNonNull(executor, "Executor 不能为空");
STRATEGY_MAP.put(strategy, executor);
}
/**
* 获取策略
*
* @param strategy 策略码
* @Return 策略
*/
public static <PARAMETER, RESULT> Executor<PARAMETER, RESULT> get(Strategy<PARAMETER, RESULT> strategy) {
return (Executor<PARAMETER, RESULT>) STRATEGY_MAP.get(strategy);
}
/**
* 判断策略是否存在
*
* @param strategy 策略码
* @return 策略是否存在
*/
public static boolean contains(Strategy<?, ?> strategy) {
return STRATEGY_MAP.containsKey(strategy);
}
/**
* 获取策略数量
*
* @return 策略数量
*/
public static int size() {
return STRATEGY_MAP.size();
}
/**
* 移除策略
*
* @param strategy 策略码
*/
public static void remove(Strategy<?, ?> strategy) {
STRATEGY_MAP.remove(strategy);
}
/**
* 清空策略
*/
public static void clear() {
STRATEGY_MAP.clear();
}
/**
* 执行策略
*
* @param strategy 策略码
* @param parameter 参数
* @return 结果
*/
@SuppressWarnings("unchecked")
public static <PARAMETER, RESULT> RESULT doExecute(Strategy<PARAMETER, RESULT> strategy, PARAMETER parameter) {
Executor<PARAMETER, RESULT> executor = (Executor<PARAMETER, RESULT>) STRATEGY_MAP.get(strategy);
if (executor == null) {
throw new IllegalStateException("未找到 Strategy 对应的 Executor: " + strategy);
}
return executor.execute(parameter);
}
}
spring 启动扫描Handler注解
[Java] 纯文本查看 复制代码 package com.jichangxiu.server.starter.action.scanner;
import com.jichangxiu.server.common.aop.utils.AopUtils;
import com.jichangxiu.server.common.core.annotation.Handler;
import com.jichangxiu.server.common.core.factory.StrategyFactory;
import com.jichangxiu.server.common.core.strategy.Executor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotatedElementUtils;
import java.util.Map;
/**
* HandlerScanner:
*
* @author Jcx
* @since 2025-01-01 00:00:00
*/
@Slf4j
public class HandlerScanner {
public HandlerScanner(ApplicationContext applicationContext) {
Map<String, Object> beans = applicationContext.getBeansWithAnnotation(Handler.class);
beans.values().forEach(bean -> {
Class<?> targetClass = AopUtils.getTargetClass(bean);
Handler handler = AnnotatedElementUtils.findMergedAnnotation(targetClass, Handler.class);
if (handler == null) {
return;
}
// 1️⃣ 校验 Executor
if (!(bean instanceof Executor<?, ?> executor)) {
log.warn("⚠️ Bean [{}] 标注了 @Handler 但未实现 Executor 接口", targetClass.getName());
return;
}
// 2️⃣ 注册
StrategyFactory.register(executor.strategy(), executor);
log.info("✅ 注册 Strategy: {} -> {}", executor.strategy(), targetClass.getSimpleName());
});
log.info("🚀 StrategyFactory 初始化完成,共 {} 个策略", StrategyFactory.size());
}
}
注册 Scanner 到 spring boot
[Java] 纯文本查看 复制代码 /**
* ActionConfig:
* Action 配置
*
* @author Jcx
* @since 2025-01-01 00:00:00
*/
@Slf4j
@AutoConfiguration
public class ActionConfig {
/**
* 策略注册 Bean
*
* @param applicationContext 应用上下文
* @return 策略注册 Bean
*/
@Bean
public HandlerScanner handlerScanner(ApplicationContext applicationContext) {
log.info("✅ 成功加载【HandlerScanner】");
return new HandlerScanner(applicationContext);
}
}
测试的类:
[Java] 纯文本查看 复制代码 package com.jichangxiu.server.application.boot.strategy.enums;
import com.jichangxiu.server.application.boot.strategy.parameter.CalcParameter;
import com.jichangxiu.server.common.core.strategy.Strategy;
import java.math.BigDecimal;
public enum CalcStrategy implements Strategy<CalcParameter, BigDecimal> {
DIV,
SUM;
}
package com.jichangxiu.server.application.boot.strategy.executor;
import com.jichangxiu.server.application.boot.strategy.enums.CalcStrategy;
import com.jichangxiu.server.application.boot.strategy.parameter.CalcParameter;
import com.jichangxiu.server.common.core.annotation.Handler;
import com.jichangxiu.server.common.core.strategy.Executor;
import com.jichangxiu.server.common.core.strategy.Strategy;
import java.math.BigDecimal;
import java.math.RoundingMode;
@Handler
public class DivExecutor implements Executor<CalcParameter, BigDecimal> {
@Override
public Strategy<CalcParameter, BigDecimal> strategy() {
return CalcStrategy.DIV;
}
@Override
public BigDecimal execute(CalcParameter calcParameter) {
BigDecimal a = calcParameter.getA();
BigDecimal b = calcParameter.getB();
return a.divide(b, RoundingMode.HALF_UP);
}
}
package com.jichangxiu.server.application.boot.strategy.executor;
import com.jichangxiu.server.application.boot.strategy.enums.CalcStrategy;
import com.jichangxiu.server.application.boot.strategy.parameter.CalcParameter;
import com.jichangxiu.server.common.core.annotation.Handler;
import com.jichangxiu.server.common.core.strategy.Strategy;
import com.jichangxiu.server.common.core.strategy.Executor;
import java.math.BigDecimal;
@Handler
public class SumExecutor implements Executor<CalcParameter, BigDecimal> {
@Override
public Strategy<CalcParameter, BigDecimal> strategy() {
return CalcStrategy.SUM;
}
@Override
public BigDecimal execute(CalcParameter calcParameter) {
BigDecimal a = calcParameter.getA();
BigDecimal b = calcParameter.getB();
return a.add(b);
}
}
package com.jichangxiu.server.application.boot.strategy.parameter;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CalcParameter {
private BigDecimal a;
private BigDecimal b;
}
package com.jichangxiu.server.application.boot.action;
import com.jichangxiu.server.application.boot.strategy.enums.CalcStrategy;
import com.jichangxiu.server.application.boot.strategy.parameter.CalcParameter;
import com.jichangxiu.server.common.core.annotation.Everyone;
import com.jichangxiu.server.common.core.factory.StrategyFactory;
import com.jichangxiu.server.starter.action.annotation.Get;
import com.jichangxiu.server.starter.action.annotation.Rest;
import java.math.BigDecimal;
@Everyone
@Rest("/strategy")
public class StrategyAction {
@Get("/test")
public String test() {
BigDecimal result = StrategyFactory.doExecute(
CalcStrategy.SUM,
new CalcParameter(
BigDecimal.valueOf(1),
BigDecimal.valueOf(2)
)
);
return "执行策略:" + result;
}
}
|