Java SpringBoot:如何使泛型类与框架不紧密耦合?

Java SpringBoot:如何使泛型类与框架不紧密耦合?,java,spring,spring-boot,Java,Spring,Spring Boot,前端开发人员正在开发我的第一个JavaSpring引导API。我已经阅读了很多关于Spring/Spring Boot中“最佳实践”的文章,并且一直在尝试重构我的代码以遵循这些实践 下面是一个通用类的示例,我使用它来处理各种服务的所有HTTP请求。最初我用注释了这个类,但正如我所提到的,我正在尝试学习并遵循Spring的“最佳实践”。我特别感兴趣的是实现所描述的内容(本文中的编号3和4)。这说明应该避免使用@component,因为我们不希望与Spring框架紧密耦合,我们希望避免“整个类路径扫

前端开发人员正在开发我的第一个JavaSpring引导API。我已经阅读了很多关于Spring/Spring Boot中“最佳实践”的文章,并且一直在尝试重构我的代码以遵循这些实践

下面是一个通用类的示例,我使用它来处理各种服务的所有HTTP请求。最初我用注释了这个类,但正如我所提到的,我正在尝试学习并遵循Spring的“最佳实践”。我特别感兴趣的是实现所描述的内容(本文中的编号3和4)。这说明应该避免使用@component,因为我们不希望与Spring框架紧密耦合,我们希望避免“整个类路径扫描”。

使用
@component
注释,我的服务可以按预期工作,但当我删除它时,会出现异常:

org.springframework.beans.factory.noSuchBean定义异常:否 类型的限定bean

这在Java中似乎是一个非常常见的例外,因为有很多关于它的问题,但这些解决方案对我来说并不奏效

我希望社区能帮助我回答的问题分为两部分:

  • 如何正确地使其成为一个与Spring不紧密耦合的可用泛型类?
  • 这实际上是一种正确的Spring开发方法,还是我对这篇文章读得太深了?

  • @Component
    添加到类中会强制使用您的类的任何人了解Spring(即Spring是编译时依赖项)

    最简单的替代方法是在应用程序中创建单独的类,用
    @Configuration
    注释,并让它处理创建Springbean类的操作

    例如:

    @Configuration
    public class MyConfiguration {
        @Bean
        public HttpService httpService() {
            return new HttpService();
        }
    }
    
    这使您的
    HttpService
    类不受Spring依赖项的影响(假设它不使用任何其他Spring注释,如
    @Autowired
    ),但它可以在您自己的应用程序中作为springbean


    请注意,您的类仍然依赖于
    restemplatebuilder
    ,它本身就是一个Spring引导类,这意味着您的类(以及任何使用它的人)将需要Spring。

    查看您链接的文章,我认为对术语“域”存在误解。“域”是应用程序生成其价值的地方。以Steam为例,搜索和购买游戏的能力产生(商业)价值。另一方面,HTTP服务是一个技术细节。是的,这是必要的,但它本身不会产生任何价值。因此,本文第3点和第4点不适用于
    HttpService

    在典型的web应用程序中,至少有三层:

    • 提供API的一个层:这些是您的端点和API使用的所有对象。例如,这包括表示端点传递/返回的请求和响应的实体
    • 提供持久性的一层:通常是存储库、DAO或任何您想要使用的持久性模型。同样,持久化单元所需的一切都应该包含在这个层中
    • 一层包含实际域:这就是我们在谈论“域”时所谈论的内容。这里我们看到了应用程序的实际功能
    现在是棘手的部分:web和数据库只不过是I/O通道。它们可以是CLI和一些文件、HTTP请求/响应和数据库,或者将来开发的任何东西。良好的软件设计允许轻松交换I/O通道,同时保留特定于域的代码。您可以在许多应用程序中看到这一点:

    • OpenShift有一个RESTAPI和一个CLI
    • AWS有一个RESTAPI和几个CLI,其中许多是第三方的
    • Steam有一个网络店面、一个桌面应用程序和一个移动客户端
    • KeyClope允许从不同来源(LDAP、OAuth2/OIDC、数据库等)提取身份验证信息
    但要获得这种灵活性,我们必须在某个地方进行隔离。什么是技术问题?什么是域名?我想要/必须解耦到多干净?在您的具体案例中:您是否将自己绑定到服务中的SpringBoot有关系吗

    为了实现这样的体系结构,我们使用模式和原则。一套众所周知的原则是最重要的。遵守这些原则的严格程度是每个人都必须为自己决定的个人问题。我个人的观点是,务实的方法通常就足够了

    我还想听听@chrylis对抽象的评论。作为软件工程师,我们喜欢沉迷于技术细节,并创建一个基本上可以处理所有事情的超级抽象。但这不是重点。它不必处理所有事情,只需要处理它的用途。如果你为客户工作:那不是客户付钱给你的。抽象总是要付出代价的。在大多数情况下,成本是复杂性和/或可读性。或者用两个比我聪明的人的话来说:和

    也就是说,应该避免使用
    @Component
    ,因为我们不希望与Spring框架紧密耦合

    它说我们不希望我们的域类与Spring紧密耦合。
    HttpService
    (它绑定到web上下文并取决于Spring的
    RestTemplateBuilder
    )和
    MySuperSpecificDomainCalculator
    (不管它放在什么上下文中都应该继续工作)之间存在差异

    。。。我们希望避免“整个类路径扫描”

    在使用类路径扫描时,我看不出有什么非常糟糕的地方。您可以让Spring扫描一小部分包。您可以精确地指向依赖于Spring的类所在的位置。带有
    @Bean
    方法的
    @Configuration
    是另一种选择

    我如何正确地使其成为可用的ge
    @Configuration
    public class MyConfiguration {
        @Bean
        public HttpService httpService() {
            return new HttpService();
        }
    }