如何在 Spring 中使用自动装配 bean 创建简单工厂模式?

2024-01-23

我有一个具有 4 个非常相似的方法的控制器,调用远程服务器上的 API 对不同类型的用户执行不同的操作。这些 API 调用之间发生的变化只是端点和一些参数。

因此,这 4 个方法都使用非常相似的代码调用服务:它们从服务器获取令牌,设置参数,返回 API 的响应。自从稍后将添加更多操作,我决定使用工厂方法模式创建 ServiceFactory 并在服务上使用模板模式以避免代码重复。

我的问题是,为了让工厂自动装配服务,它需要与它们耦合,我必须@Autowire每一次实施。有更好的解决方案吗?

这是我到目前为止的代码:

休息控制器

@RestController
public class ActionController {
  @Autowired
  private SsoService ssoService;

  // this is the factory
  @Autowired
  private ServiceFactory factory;

  @PostMapping("/action")
  public MyResponse performAction(@RequestBody MyRequest request, HttpServletRequest req) {
    // template code (error treatment not included)
    request.setOperator(ssoService.getOperator(req));
    request.setDate(LocalDateTime.now());
    return serviceFactory.getService(request).do();
  }
}

服务工厂

@Component
public class ServiceFactory {

  @Autowired private ActivateUserService activateUserService;
  @Autowired private Action2UserType2Service anotherService;
  //etc

  public MyService getService(request) {
    if (Action.ACTIVATE.equals(request.getAction()) && UserType.USER.equals(request.getUserType()) {
      return activateUserService;
    }
    // etc
    return anotherService;
  }
}

Service Base,实现MyService接口

public abstract class ServiceBase implements MyService {

  @Autowired private ApiService apiService;
  @Autowired private ActionRepository actionRepository;
  @Value("${api.path}") private String path;

  @Override
  public MyResponse do(MyRequest request) {
    String url = path + getEndpoint();
    String token = apiService.getToken();

    Map<String, String> params = getParams(request);
    // adds the common params to the hashmap

    HttpResult result = apiService.post(url, params); 
    if (result.getStatusCode() == 200) {
      // saves the performed action
      actionRepository.save(getAction());
    }
    // extracts the response from the HttpResult
    return response;
  }
}

服务实施(共有4个)

@Service
public class ActivateUserService extends ServiceBase {
  @Value("${api.user.activate}")
  private String endpoint;

  @Override
  public String getEndpoint() {
    return endpoint;
  }

  @Override
  public Map<String,String> getParams(MyRequest request) {
    Map<String, String> params = new HashMap<>();
    // adds custom params
    return params;
  }

  @Override
  public Action getAction() {
    return new Action().type(ActionType.ACTIVATED).userType(UserType.USER);
  }
}

You can @Autowired a List of MyService,这将创建一个List所有实现了MyService界面。然后你可以添加一个方法MyService接受一个MyRequest对象并决定它是否可以处理该请求。然后您可以过滤List of MyService找到第一个MyService可以处理请求的对象。

例如:

public interface MyService {

    public boolean canHandle(MyRequest request);

    // ...existing methods...
}

@Service
public class ActivateUserService extends ServiceBase {

    @Override
    public boolean canHandle(MyRequest request) {
        return Action.ACTIVATE.equals(request.getAction()) && UserType.USER.equals(request.getUserType());
    }

    // ...existing methods...
}

@Component
public class ServiceFactory {

    @Autowired
    private List<MyService> myServices;

    public Optional<MyService> getService(MyRequest request) {
        return myServices.stream()
            .filter(service -> service.canHandle(request))
            .findFirst();
    }
}

请注意,ServiceFactory上面的实现使用 Java 8+。如果 Java 8 或更高版本无法实现,您可以实现ServiceFactory按以下方式进行类:

@Component
public class ServiceFactory {

    @Autowired
    private List<MyService> myServices;

    public Optional<MyService> getService(MyRequest request) {

        for (MyService service: myServices) {
            if (service.canHandle(request)) {
                return Optional.of(service);
            }
        }

        return Optional.empty();
}

有关使用的更多信息@Autowired with List, see 按类型将引用 bean 自动装配到列表中 https://stackoverflow.com/questions/7446301/autowire-reference-beans-into-list-by-type.


该解决方案的核心是移动决定是否MyService实现可以处理MyRequest来自ServiceFactory(外部客户)MyService实施本身。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Spring 中使用自动装配 bean 创建简单工厂模式? 的相关文章

  • 使用 Spring MVC 返回 PDF 文件

    实际上 我有这个功能 我有一个框架 可以在其中设置 URL ip port birt preview report report rptdesign format pdf parameters 并且该框架呈现 PDF 文件 但我想隐藏该网址
  • java替代Thread.stop()来中断特定调用

    我正在寻找一种方法来告诉这个调用 大约需要 20 120 秒 final Area image final AffineTransform transform new AffineTransform transform scale imag
  • 使用 xuggle 将 mp3 转换为 wav 出现异常

    我正在尝试将 mp3 转换为 wav 代码在这里 String mp3 F work pic2talk38512 mp3 String wav F work pic2talk38512 wav TranscodeAudioAndVideo
  • Java,将 null 分配给对象和仅声明之间有什么区别

    之间有什么区别 Object o null and Object o 仅声明 有人可以回答我吗 这取决于您声明变量的范围 例如 局部变量没有default values在这种情况下你将不得不分配null手动 在这种情况下实例变量分配 nul
  • 我们如何测试我们的 Java UI?

    我们正在寻找记录和回放类型的测试工具来自动化我们的一些 UI 功能测试 我们已经研究了从 Silke 到 QTP 的大多数常见嫌疑 但没有一个起作用 当需要右键单击才能从右键单击菜单中选择某些内容时 或者当您必须在网格的下拉列表中选择一个值
  • 使用 java 的 RAR 档案 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Java 9 中可以使用提前编译吗?

    As per JEP 295 http openjdk java net jeps 295 任何 JDK 模块 类或用户代码的 AOT 编译都是实验性的 JDK 9 中不支持 要使用 AOT 化的 java base 模块 用户必须编译该模
  • 根据哈希值确认文件内容

    我需要 检查完整性 content文件数量 文件将写入 CD DVD 可能会被复制多次 这个想法是识别正确复制的副本 在从 Nero 等中删除它们之后 我对此很陌生 但快速搜索表明Arrays hashCode byte http down
  • Java 反射:如何检索匿名内部类?

    我在另一个类中有一个匿名内部类 SomeClass Both SomeClass class getClasses and SomeClass class getDeclaredClasses 返回空数组 我在中找不到一些关于此的提示Cla
  • 在 JavaFX 中拖动未装饰的舞台

    我希望将舞台设置为 未装饰 使其可拖动且可最小化 问题是我找不到这样做的方法 因为我遇到的示例是通过插入到主方法中的方法来实现的 我想通过控制器类中声明的方法来完成此操作 就像我如何使用下面的 WindowClose 方法来完成此操作 这是
  • java.lang.IllegalArgumentException:addChild:子名称“/”不唯一

    java lang IllegalArgumentException addChild 子名称 不唯一 通过在 tomcat webapps 文件夹中启用和禁用 saml 单点登录来替换现有 war 文件时遇到此问题 我正在使用 apach
  • Akka 和 spring 配置

    我正在尝试将 akka 与 spring 结合起来 但没有成功 基本上 我的应用程序似乎不习惯读取 akka 模式 具有架构的 service context xml 的一部分
  • 多对多不检索映射数据

    Spring boot 2 5 6 我无法安装版本 概要文件 java Getter Setter NoArgsConstructor AllArgsConstructor EqualsAndHashCode FieldDefaults l
  • 处理照片上传的最佳方式是什么?

    我正在为一个家庭成员的婚礼制作一个网站 他们要求的一个功能是一个照片部分 所有客人都可以在婚礼结束后前往并上传他们的照片 我说这是一个很棒的想法 然后我就去实现它 那么只有一个问题 物流 上传速度很慢 现代相机拍摄的照片很大 2 5 兆 我
  • Microsoft JDBC 中的 JTDS 属性相当于什么?

    我正在将 JTDS 连接更改为 Microsoft JDBC 并且我看到存在于http jtds sourceforge net faq html http jtds sourceforge net faq htmlMicrosoft JD
  • 如何使用 Nimbus LookAndFeel 更改 JToolTip 的背景颜色?

    在使用 Nimbus LookAndFeel 的基于 Swing 的 Java 应用程序中 我尝试设置工具提示的背景颜色 因此 我创建了 JToolTip 的子类 并通过重写 createToolTip 在我的组件中使用它 到目前为止一切正
  • Java 相当于 Python 的 urllib.urlencode(基于 HashMap 的 UrlEncode)

    From https stackoverflow com questions 2018026 should i use urllib or urllib2 2018103 2018103 Java 中 Python 的 urllib url
  • Python 可以替代 Java 小程序吗?

    除了制作用于物理模拟 如抛射运动 重力等 的教育性 Java 小程序之外 还有其他选择吗 如果你想让它在浏览器中运行 你可以使用PyJamas http pyjs org 这是一个 Python 到 Javascript 的编译器和工具集
  • 如何隐藏或删除 Android HoneyComb 中的状态栏?

    如何隐藏或删除 Android HoneyComb 中的状态栏 每次运行应用程序时 我都会发现某些内容必须被状态栏覆盖 我尝试改变AndroidManifest xml 但没有任何改变 你不知道 它被认为是永久的屏幕装饰 就像电容式主页 菜
  • 使用 Hibernate 防止无限循环数据检索

    我想知道 想象一个场景 例如 POJO public class User private String userName private String name private String surname private List

随机推荐

  • 在 Typescript 中向创建的 Redux Store 添加属性

    当我在 Typescript 中创建新的 Redux Store 时 我在添加属性时遇到问题 const bindMiddleware middleware gt if process env NODE ENV production con
  • 使用 kotlin.UByte 作为房间实体不起作用

    我想将以下数据类存储在我的房间数据库中 不知怎的 我没有成功 Entity data class UInt8 PrimaryKey autoGenerate true var key Int var name String uint8 te
  • 如何将方法参数声明为任何枚举

    我有一个方法 需要将枚举作为参数传递 public
  • 如何刷新实体主页视图上的列表

    我的 CRM 2011 实体之一上有一个自定义功能区按钮 可以有效禁用该实体 然后我想刷新该实体主页上的当前视图 我希望这个由 JS 触发 目前 我可以刷新整个父窗口 这将使我回到仪表板 而不是该实体的主页 Thanks 好问题 您可以通过
  • notepad ++ 中的 EOL 转换

    由于某种原因 当我在 Windows 计算机上从 unix 服务器打开文件时 它们偶尔会进行 Macintosh EOL 转换 并且当我再次编辑 保存它们时 它们无法在 unix 服务器上正常工作 我只使用记事本 从这个unix服务器编辑文
  • Haskell 错误:“没有 (Enum [Int]) 的实例

    我有以下代码 betaRest Int gt Int gt Int betaRest n prevDigits n 0 length prevDigits otherwise sum map betaRest n 1 0 9 betaFir
  • gitolite hooks - 接收后似乎不起作用

    我在我的仓库中配置了 gitolite 我看到了 gitolite 文献中记录的 2 个钩子副本 我希望服务器端挂钩 post receive 在有人推送到存储库时发送电子邮件 我正在使用 git notifier 但是 当我推动时什么也没
  • 文本区域高度增加

    当我们打字时 如何将文本区域的高度从 18 像素增加到最大 50 像素 那么如果有人输入更多内容 滚动条应该接管 这可能吗 您可以使用以下任一插件 文本扩展器 演示 http blogs sitepointstatic com exampl
  • 使用git子树合并,同时也在所有合并子树的所有分支中进行合并

    我想使用一个流行的开源问题跟踪器 Redmine 它提供 git 集成 不幸的是 跟踪器中的每个项目只能与一个 git 存储库关联 在跟踪器中创建多个项目不是我的理想设置 考虑到这一点 我尝试使用 git 子树合并 解释为here http
  • 如何通过 Google 图表 API 使用 X 轴日期?

    有没有办法使用 Google 图表 API 绘制图表 以便 X 轴值是一个月中的天数 我的数据点没有以相同的频率提供 例如 Date Value 1 1 2009 100 1 5 2009 150 1 6 2009 165 1 13 200
  • 如何获得实时期权链?

    如何获取实时期权链 每分钟或如果可能的话 每秒 另外 我想每次刷新包含此数据 从Python导出 的excel 以便可以刷新图表 我编写了下面的代码来获取日终数据 spot market inputs s ticker ITC start
  • 边距和负边距

    我一直以为我理解边距和负边距 但显然我不明白 我刚刚开始新的设计 但已经遇到了问题 我有一个 div hill3Cont 和另一个 div hill3Hill 嵌套在里面 这是它们的 CSS hill3Cont width 100 back
  • 在android上添加OnLongClickListener支持TabLayout | TabLayout.Tab

    我正在使用服务库中找到的 TabLayout 我尝试在长按选项卡时添加 OnLongClickListener 这对我来说是不可能的 我什至尝试使用 childViews 来 破解 它 View tabLayoutChild tabLayo
  • 自定义 TF 对象检测边界框厚度和标签字体大小

    运行预测https github com tensorflow models blob master research object detection object detection tutorial ipynb https githu
  • 如何在VSCode中设置“终止正在运行的任务”的键盘快捷键?

    我让我的构建运行我的应用程序 直到我杀死它 这工作正常 但最好将 终止正在运行的任务 绑定到键盘快捷键 这可能吗 当您要更改键绑定时 会列出所有命令 因此您可以将如下内容添加到用户设置中 key shift cmd s command wo
  • 自动拉伸表格单元格 div css

    我知道有很多类似的问题 但没有一个能帮助我解决这个问题 我有非常简单的设置 wrapper width 100 display table dontBreakmyLine display table cell iCanUseWhatIsLe
  • HTTP基本认证,使用python

    我希望我的用户访问我的域上的受保护目录 htaccess 和 htpasswd 均已创建并驻留在受保护的库中 要求输入用户名 密码组合的 html 是
  • 如何在工作组安装上以编程方式清除 MSMQ 系统队列日志?

    我试试这个 MessageQueue mq new MessageQueue Journal mq Purge 它在 XP 上运行良好 但是 在Windows 2003服务器上 我总是遇到这个错误 工作组安装计算机不支持该操作 系统队列的正
  • 从字符串中提取主机名

    我想只匹配 URL 的根 而不是文本字符串中的整个 URL 鉴于 http www youtube com watch v ClkQA2Lb iE http youtu be ClkQA2Lb iE http www example com
  • 如何在 Spring 中使用自动装配 bean 创建简单工厂模式?

    我有一个具有 4 个非常相似的方法的控制器 调用远程服务器上的 API 对不同类型的用户执行不同的操作 这些 API 调用之间发生的变化只是端点和一些参数 因此 这 4 个方法都使用非常相似的代码调用服务 它们从服务器获取令牌 设置参数 返