共计 3558 个字符,预计需要花费 9 分钟才能阅读完成。
原题目: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)、主动配置等等,但这意味着提供一个心理框架来了解何时利用哪种配置,以便您能够专一于使工作软件平安疾速地投入生产的重要工作。