0
点赞
收藏
分享

微信扫一扫

计算机三级等级考试

穿裙子的程序员 2024-06-06 阅读 26

目录

序言

策略模式大家都应该了解或者使用过,此篇文章中就不再阐述,之前springboot项目中小编也真正的实战应用过。现在换Quarkus框架开发项目,为了后期的项目业务的可扩展以及高可用,就构思并了解如何在Quarkus中使用,软件设计思想最重要,换组件无非换种语法而已,但是也需要摸索,排坑之类,下面给出一个简单的示例demo:模拟向不同的平台类型发送消息

自定义注解

基于Quarkus自定义注解的语法格式,与java语法基本一致,毕竟遵循 MicroProfile 和 Jakarta EE 的规范。

  • 核心代码
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
public @interface Platform {
    PlatformTypeEnum type();
}
  • 平台类型枚举
@AllArgsConstructor
@Getter
public enum PlatformTypeEnum {
    //企微
    WEWORK(1, "企微"),
    //小红书
    RED_BOOK(2, "小红书"),
    ;
    private final Integer type;
    private final String desc;
}

业务接口

抽象消息业务接口,应用于多平台渠道实现

public interface MessageService {

    String sendMsg(String msg);


}

渠道消息实现

  • 企业微信渠道实现
@Platform(type = PlatformTypeEnum.WEWORK)
@Dependent
public class WeWorkMessage implements MessageService {

    @Inject
    MessageRepo messageRepo;
    @Override
    public String sendMsg(String msg) {
        //TODO
        return messageRepo.getMessage() + ", weWork";
    }
}

  • 小红书渠道消息实现
@Platform(type = PlatformTypeEnum.RED_BOOK)
@Dependent
public class RedBookMessage implements MessageService {
    @Override
    public String sendMsg(String msg) {
        //TODO
        return "redBook";
    }
}

策略分发

  • 方式一:switch-case
  public MessageService getStrategy(PlatformTypeEnum platform) {
        switch (platform) {
            case WEWORK:
                return messageServices.select(WeWorkMessage.class).get();
            case RED_BOOK:
                return messageServices.select(RedBookMessage.class).get();
            default:
                return null;
        }
    }

这种方式违反了开闭原则,每次增加子类都需要修改此处的代码;

  • 方式二:动态分发
@ApplicationScoped
public class MessageStrategy {
    @Inject
    @Any
    Instance<MessageService> messageServices;
    public MessageService getStrategy(PlatformTypeEnum platform) {
        return messageServices.select(new PlatformLiteral(platform)).get();
    }
    private static class PlatformLiteral extends AnnotationLiteral<Platform> implements Platform {
        private final PlatformTypeEnum platform;

        public PlatformLiteral(PlatformTypeEnum platform) {
            this.platform = platform;
        }

        @Override
        public PlatformTypeEnum type() {
            return platform;
        }
    }
}

getStrategy 方法使用 messageServices.select 方法来动态选择符合条件的 MessageService 实例。
PlatformLiteral 用于在运行时创建一个带有具体值的 @Platform 注解。
PlatformLiteral 类扩展了 AnnotationLiteral 并实现了 Platform 接口。它接受一个 PlatformTypeEnum 值并重写 type 方法返回该值。通过这种方式,PlatformLiteral 在运行时创建了一个带有特定 PlatformTypeEnum 值的 @Platform 注解实例。

  • 优点
    这个机制允许在运行时动态选择不同的 MessageService 实现,而无需在编译时确定具体的实现类。

测试

@Path("/message")
@Tag(name = "消息")
public class MessageController {

    @Inject
    MessageStrategy messageStrategy;

    @Path("/get-msg")
    @GET
    public Response<String> getMsg(@QueryParam("platform") PlatformTypeEnum platform) {
        String test = messageStrategy.getStrategy(platform).sendMsg("test");
        return Response.ok(test);
    }
}

可以看到messageService中存在两个实现类
在这里插入图片描述
使用swagger测试,分布使用企微、小红书入参得到的结果如图:
在这里插入图片描述

  • 小红书,消息渠道分发
    在这里插入图片描述

知识扩展

基于方式二实现扩展使用的注解语法以及相关原理

@Any

  • 应用场景
    @Any 注解在 CDI(Context and Dependency Injection)中用于注入所有符合特定类型的 Bean 实例,而不考虑其他限定符。它通常用于动态选择或处理多个实现。

  • 语法

@Inject
@Any
Instance<SomeType> someInstances;
  • 原理
    @Any 告诉 CDI 容器注入所有符合类型 SomeType 的 Bean 实例,即使这些实例有其他限定符。

  • @Any注解的源码,是不是很熟悉呀

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
@Documented
public @interface Any {
    public static final class Literal extends AnnotationLiteral<Any> implements Any {
        public static final Literal INSTANCE = new Literal();
        private static final long serialVersionUID = 1L;

        public Literal() {
        }
    }
}

AnnotationLiteral 应用场景和语法

  • 应用场景
    AnnotationLiteral 用于在运行时动态创建注解实例。它通常用于 CDI 的动态选择,特别是当需要根据条件在运行时选择特定 Bean 实例时。

  • 语法

public class SomeAnnotationLiteral extends AnnotationLiteral<SomeAnnotation> implements SomeAnnotation {
    private final SomeType value;

    public SomeAnnotationLiteral(SomeType value) {
        this.value = value;
    }

    @Override
    public SomeType value() {
        return value;
    }
}

  • 原理
    AnnotationLiteral 是一个抽象类,用于表示注解的具体实例,提供了注解的具体实现,使得可以在运行时生成注解实例,用于 CDI 的选择操作。原理是利用泛型和反射机制,它通过创建一个匿名内部类来实现对注解实例的动态创建,通过扩展 AnnotationLiteral 类并实现注解接口的方法,可以动态创建带有具体值的注解实例,而不是依赖于编译时注解处理器生成的实例。
举报

相关推荐

0 条评论