1、创建注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Component
public @interface StrategyFlag {
    //标识
    String value();
}
/**
 * 策略方法
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface StrategyHandler {
}

2、定义交换器

/**
 * 转换器
 */
public interface StrategyRunner {

    //根据注册标识调用相对应的方法
    void run(String flag);
}

3、配置类

@Configuration
public class StrategyConfig implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Bean
    public StrategyRunner strategyRunner() {
        Map<String, Object> strategyClass = applicationContext.getBeansWithAnnotation(StrategyFlag.class);
        // 策略处理函数
        Map<String, Function<Void, Void>> strategyHandlers = new HashMap<>();
        for (Object s : strategyClass.values()) {
            // 获取策略标识
            String flag = s.getClass().getAnnotation(StrategyFlag.class).value();
            for (Method m : s.getClass().getMethods()) {
                // 如果方法标注了StrategyHandler注解,则封装成可调用对象加入strategyHandlers
                if(m.isAnnotationPresent(StrategyHandler.class)){
                    strategyHandlers.put(flag, ignored -> {
                        try {
                            m.invoke(s);
                            return null;
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    });
                    break;
                }
            }
        }
        return flag -> strategyHandlers.get(flag).apply(null);
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

4、实现

@StrategyFlag("s1")
public class Strategy1 {
    @StrategyHandler
    public void handleStrategy1() {
        System.out.println("strategy 1");
    }
}

@StrategyFlag("s2")
public class Strategy2 {
    @StrategyHandler
    public void handleStrategy2() {
        System.out.println("strategy 2");
    }
}

@RestController
@RequestMapping("/hello")
public class HelloController {

    @Autowired
    private StrategyRunner strategyRunner;


    @RequestMapping("/")
    public String hello(){
        strategyRunner.run("s1");
        strategyRunner.run("s2");
        return "hello";
    }
}


问题:每个策略都要创建一个类,如果一个类想要多个方法执行不同的策略则会比较受限,并且现在没有返回值

优化:

1、修改 @StrategyHandler

/**
 * 该注解作用为每个方法对应标识
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface StrategyHandler {

    // 标识
    String value();
}

2、修改交换器

/**
 * 转换器
 */
public interface StrategyRunner {

    //根据注册标识调用相对应的方法。修改返回值类型为object
    Object run(String flag);
}

3、修改配置类

@Configuration
public class StrategyConfig implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Bean
    public StrategyRunner strategyRunner() {
        Map<String, Object> strategyClass = applicationContext.getBeansWithAnnotation(StrategyFlag.class);
        // 策略处理函数,返回值类型为Object
        Map<String, Function<Void, Object>> strategyHandlers = new HashMap<>();
        for (Object s : strategyClass.values()) {
            // 获取策略标识
            String flag = s.getClass().getAnnotation(StrategyFlag.class).value();
            for (Method m : s.getClass().getMethods()) {
                // 如果方法标注了StrategyHandler注解,则封装成可调用对象加入strategyHandlers
                if(m.isAnnotationPresent(StrategyHandler.class)){
                    //获取方法上面的标识
                    String value = m.getAnnotation(StrategyHandler.class).value();
                    //将策略表示和相对应的方法放在一起
                    strategyHandlers.put(value, ignored -> {
                        try {
                            return m.invoke(s);
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    });
                }
            }
        }
        return flag -> strategyHandlers.get(flag).apply(null);
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

3、实现

@StrategyFlag("s1")
public class Demo {

    @StrategyHandler("alipay")
    public String alipay() {
        System.out.println("alipay");
        return "helloAliPay";
    }

    @StrategyHandler("payple")
    public void payple() {
        System.out.println("payple");
    }
}

@StrategyFlag("t1")
public class Test {

    @StrategyHandler("boxingMatch")
    public void jump() {
        System.out.println("拳击");
    }

    @StrategyHandler("wrestlingCompetition")
    public void payple() {
        System.out.println("摔跤");
    }
}

@RestController
@RequestMapping("/hello")
public class HelloController {

    @Autowired
    private StrategyRunner strategyRunner;


    @RequestMapping("/")
    public String hello(){
        System.out.println(strategyRunner.run("alipay"));
        strategyRunner.run("payple");
        strategyRunner.run("boxingMatch");
        strategyRunner.run("wrestlingCompetition");
        return "hello";
    }
}

更多推荐