首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为 Spring Framework 和 Spring Boot 构建代码

为 Spring Framework 和 Spring Boot 构建代码

原创
作者头像
IT胶囊
修改2021-09-06 18:00:41
6270
修改2021-09-06 18:00:41
举报
文章被收录于专栏:IT技能应用IT技能应用

原标题:Spring认证|为 Spring Framework 和 Spring Boot 构建代码

如何为 Spring 框架构建心理框架

下面有一个很好的评论,提到原始标题Structuring Spring Boot Applications有点误导,因为该博客不打算谈论如何组织类型和包,而是考虑 Spring 如何与代码中的对象。下一段试图澄清这一点,但显然没有达到。无论如何,我已经更改了它,不幸的是这会破坏早期的链接。我对糟糕的标题和现在两天的链接断开感到抱歉。我希望它对每个人都有用,即使我显然可以用标题做得更好......

很难考虑构建应用程序。在更高级别有很多需要考虑的事情——它是批处理作业、Web 应用程序、消息应用程序等。框架——分别是 Spring Batch、Spring Webflux、Spring Integration——将指导这些决策。除此之外,还有许多其他框架,它们是量身定制的,可帮助您为特定的垂直业务构建值得生产的东西。我们不会在这篇文章中探讨这些。相反,我想回答这个问题:我们如何构建我们的配置?

我不能给你一个固执的答案,希望在一篇文章中适合它,但我们可以讨论 2021 年 Spring Boot 应用程序中配置的技术维度。 更容易谈论如何构建你的 Java 对象以使其正常工作在控制反转 (IoC) 容器中。请记住,归根结底,Spring 是一大袋对象。它需要知道您希望如何安排您的对象——它们如何连接以及它们如何相互关联——以便为它们提供服务。例如,它可以在方法启动和停止时开始和提交事务。它可以创建 HTTP 端点,在请求到达时调用您的 Spring 控制器处理程序方法。它可以调用您的消息侦听器对象来响应来自 Apache Kafka 代理或 AWS SQS 或 RabbitMQ 或其他任何东西的新消息。

Spring 有一个对象的元模型——它有点像 Java 反射 API。它知道哪些类有注释。它知道哪些对象有构造函数。它知道给定对象依赖于哪些依赖项、哪些 bean 和哪种类型。你的工作是帮助它建立这个元模型来为你管理所有的对象。例如,如果它可以控制对象的创建,那么它也可以在创建对象之前更改对象的创建。

Spring 只能为您提供所有这些服务,前提是它知道对象是如何连接在一起的。所以这个想法是你给 Spring 普通的 Java 对象 (POJO),它会检测它们上的注释并使用这些注释来连接你的服务的行为。但是,当然,除非它控制 Java 对象的创建,否则它不能这样做。

在幕后,它通过创建一个 Java InvocationHandler(一个 JDK 代理)或者更常见的方法是使用 CGLIB 之类的东西来创建一个扩展 Java 类的新类。这个类是你的类的子类。所以,想象一下你有一个这样的类:

class CustomerService  { private final JdbcTemplate template; CustomerService (JdbcTemplate jt) { this.JdbcTemplate = jt; }    @Transactional public void updateCustomer ( long customerId, String name){       // .. . }}复制

您希望 Spring 在每次调用该方法时自动启动和停止事务。为此,Spring 需要在调用方法之前和之后插入自身。在幕后,它会做这样的事情:

class SpringEnhancedCustomerService extends CustomerService {

 // Spring provides a reference from the applicationContext of type JdbcTemplate

SpringEnhancedCustomerService (JdbcTemplate jt) {

super(JdbcTemplate ) ;

}

@Override

public void updateCustomer (long customerId, String name) {

// call Java code to start a JDBC transaction

super.updateCustomer(customerId, name);

// call Java code to stop a JDBC transaction

}}复制

在您的代码中,您可以注入对CustomerService. 你仍然会得到一个,但不是你创建的那个。相反,您将获得子类。正是这个魔术 - 你要一顶帽子,然后得到一顶带有兔子的帽子 - 让 Spring 如此强大。

因此,Spring 必须了解您的对象。有很多方法可以做到这一点。

一是你可以非常明确。在 Spring Boot 之前,您有两个标准选项:XML 和 Java 配置。然而,那是 2013 年及更早的时间。现在,我们不鼓励使用 XML,因此只剩下 Java 配置了。下面是一个例子:

@Configuration class ServiceConfiguration {

@Bean DataSource h2DataSource (){

return ... ;

}

@Bean JdbcTemplate JdbcTemplate (DataSource ds) {

return new JdbcTemplate(ds);

}

@Bean CustomerService customerService (JdbcTemplate jdbcTemplate) {

return new CustomerService (jdbcTemplate);

}}复制

在这里,您正在创建三个对象并显式地将事物连接在一起。当 Spring 启动时,它会找到@Configuration类,调用所有用 注释的方法@Bean,将所有返回值存储在应用程序上下文中,并使它们可用于注入。如果该方法似乎需要参数,它会查找任何其他返回该类型值的方法并首先调用它。然后将该值作为参数注入到方法中。如果它已经为其他注入调用了该方法,它只会重用已经创建的实例。

这种方法受益于显式——关于你的对象如何连接的所有信息都在一个地方——配置类。但是,对于您创建的类,您在两个不同的位置拥有知识:类本身和配置类。

因此,您可以使用另一种更隐式的方法:组件扫描。在这种方法中,Spring 在类路径上查找具有构造型注释的类,例如@Component或@Controller。所有构造型注释最终都用@Component. @Component是最低、最无差别的注释。如果你看@Controller,它是用@Component. 如果你看@RestController,它是用@Controller. 有 3 位间接寻址,但是用 注释的类@RestController仍然至少像用 注释的类一样对待@Component。专门的注释增加了专门的处理,但它们仍然是 的专门化@Component,而不是它的替代品。

因此,我们可能会认为CustomerService在配置类中定义和配置它很烦人。毕竟,如果 Spring 只知道类,它肯定可以自己弄清楚其余的关系吗?它可以查看构造函数并看到,要构造 的实例CustomerService,它需要对 的引用JdbcTemplate,该引用已在别处定义。

所以,这就是组件扫描的作用。您可以向类添加@Service另一个带有@Component,注释@Bean的构造型注释,然后删除配置类中的方法。Spring 将自动创建服务,它将提供所需的依赖项。它还将对类进行子类化以提供这些服务。

我们正在取得进展,移除更多样板。但是DataSource和JdbcTemplate呢?您需要它们,但您肯定不必每次都重新创建它们吗?这就是 Spring Boot 的洞察力。在创建类或调用方法之前,它使用@Condition注释来装饰用注释的类@Component或@Configuration评估测试@Bean。这些测试可以在环境中寻找线索。例如,假设您有 H2 - 类路径上的嵌入式 SQL 数据库。并且您spring-jdbc在包含JdbcTemplate该类的类路径上拥有该库。它可以使用测试来测试类路径上是否存在这些类,并推断出您想要一个嵌入式 SQLDataSource并且您想要一个JdbcTemplate与新生成的SQL连接的实例DataSource. 它有自己的配置来为你提供这些 bean。现在,您可以@Configuration完全放弃课程!Spring Boot 提供了两个 bean,并基于构造型注释隐含了另一个 bean。

我们已经研究了 Spring IoC 容器的基本动机,并且我们已经研究了 IoC 容器如何工作以帮助满足框架提出的承诺。

我们确实可以走得更远,探索面向方面的编程 (AOP)、自动配置等等,但这意味着提供一个心理框架来理解何时应用哪种配置,以便您可以专注于使工作软件安全快速地投入生产的重要工作。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档