《SpringBoot揭秘:快速构建微服务体系》—第2章2.3节 了解一点儿JavaConfig

本文涉及的产品
云原生网关 MSE Higress,422元/月
注册配置 MSE Nacos/ZooKeeper,118元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 本节书摘来自华章出版社《SpringBoot揭秘:快速构建微服务体系》一书中的第2章,第2.2节了解一点儿JavaConfig,作者王福强,更多章节内容可以访问云栖社区“华章计算机”公众号查看。 2.3 了解一点儿JavaConfig Java 5的推出,加上当年基于纯Java Annotation的依赖注入框架Guice的出现,使得Spring框架及其社区也“顺应民意”,推出并持续完善了基于Java代码和Annotation元信息的依赖关系绑定描述方式,即JavaConfig项目。

本节书摘来自华章出版社《SpringBoot揭秘:快速构建微服务体系》一书中的第2章,第2.2节了解一点儿JavaConfig,作者王福强,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.3 了解一点儿JavaConfig
Java 5的推出,加上当年基于纯Java Annotation的依赖注入框架Guice的出现,使得Spring框架及其社区也“顺应民意”,推出并持续完善了基于Java代码和Annotation元信息的依赖关系绑定描述方式,即JavaConfig项目。
基于JavaConfig方式的依赖关系绑定描述基本上映射了最早的基于XML的配置方式,比如:
(1)表达形式层面
基于XML的配置方式是这样的:


08f73fff8c5914b2d838d3bc29a27148734e2578


7de69f0a7bf46912dea33b712c9680f75a93d6d4
<!-- bean定义 -->


而基于JavaConfig的配置方式是这样的:
@Configuration
public class MockConfiguration{

// bean定义

}
任何一个标注了@Configuration的Java类定义都是一个JavaConfig配置类。
(2)注册bean定义层面
基于XML的配置形式是这样的:

...


而基于JavaConfig的配置形式是这样的:

@Configuration
public class MockConfiguration {
    @Bean
    public MockService mockService() {
        return new MockServiceImpl();
    }
}

任何一个标注了@Bean的方法,其返回值将作为一个bean定义注册到Spring的IoC容器,方法名将默认成为该bean定义的id。
(3)表达依赖注入关系层面
为了表达bean与bean之间的依赖关系,在XML形式中一般是这样的:

<bean id="mockService" class="..MockServiceImpl">
    <property name="dependencyService" ref="dependencyService"/>
</bean>


而在JavaConfig中则是这样的:

@Configuration
public class MockConfiguration {

    @Bean
    public MockService mockService() {
        return new MockServiceImpl(dependencyService());
    }

    @Bean
    public DependencyService dependencyService() {
        return new DependencyServiceImpl();
    }
}

如果一个bean的定义依赖其他bean,则直接调用对应JavaConfig类中依赖bean的创建方法就可以了。
在JavaConfig形式的依赖注入过程中,我们使用方法调用的形式注入依赖,如果这个方法返回的对象实例只被一个bean依赖注入,那也还好,如果多于一个bean需要依赖这个方法调用返回的对象实例,那是不是意味着我们就会创建多个同一类型的对象实例?
从代码表述的逻辑来看,直觉上应该是会创建多个同一类型的对象实例,但实际上最终结果却不是这样,依赖注入的都是同一个Singleton的对象实例,那这是如何做到的?
笔者一开始以为Spring框架会通过解析JavaConfig的代码结构,然后通过解析器转换加上反射等方式完成这一目的,但实际上Spring框架的设计和实现者采用了另一种更通用的方式,这在Spring的参考文档中有说明,即通过拦截配置类的方法调用来避免多次初始化同一类型对象的问题,一旦拥有拦截逻辑的子类发现当前方法没有对应的类型实例时才会去请求父类的同一方法来初始化对象实例,否则直接返回之前的对象实例。
所以,原来Spring IoC容器中有的特性(features)在JavaConfig中都可以表述,只是换了一种形式而已,而且,通过声明相应的Java Annotation反而“内聚”一处,变得更加简洁明了了。
2.3.1 那些高曝光率的Annotation
至于@Configuration,我想前面已经提及过了,这里不再赘述,下面我们看几个其他比较常见的Annotation,便于为后面更好地理解SpringBoot框架的奥秘做准备。

  1. @ComponentScan
    @ComponentScan对应XML配置形式中的元素,用于配合一些元信息Java Annotation,比如@Component和@Repository等,将标注了这些元信息Annotation的bean定义类批量采集到Spring的IoC容器中。

我们可以通过basePackages等属性来细粒度地定制@ComponentScan自动扫描的范围,如果不指定,则默认Spring框架实现会从声明@ComponentScan所在类的package进行扫描。
@ComponentScan是SpringBoot框架魔法得以实现的一个关键组件,大家可以重点关注,我们后面还会遇到它。

  1. @PropertySource与@PropertySources
    @PropertySource用于从某些地方加载*.properties文件内容,并将其中的属性加载到IoC容器中,便于填充一些bean定义属性的占位符(placeholder),当然,这需要PropertySourcesPlaceholderConfigurer的配合。

如果我们使用Java 8或者更高版本开发(本书写作期间Java 9还没发布),那么,我们可以并行声明多个@PropertySource:

@Configuration
@PropertySource("classpath:1.properties")
@PropertySource("classpath:2.properties")
@PropertySource("...")
public class XConfiguration{
    ...
}

如果我们使用低于Java 8版本的Java开发Spring应用,又想声明多个@PropertySource,则需要借助@PropertySources的帮助了:

@PropertySources({
        @PropertySource("classpath:1.properties"),
        @PropertySource("classpath:2.properties"),
        ...
})
public class XConfiguration{
    ...
}
}
  1. @Import与@ImportResource
    在XML形式的配置中,我们通过的形式将多个分开的容器配置合到一个配置中,在JavaConfig形式的配置中,我们则使用@Import这个Annotation完成同样目的:
@Configuration
@Import(MockConfiguration.class)
public class XConfiguration {
    ...
}

@Import只负责引入JavaConfig形式定义的IoC容器配置,如果有一些遗留的配置或者遗留系统需要以XML形式来配置(比如dubbo框架),我们依然可以通过@ImportResource将它们一起合并到当前JavaConfig配置的容器中:

@Configuration
@Import(MockConfiguration.class)
@ImportResource("...")
public class XConfiguration {
相关文章
|
6天前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
21 4
|
8天前
|
Java API 数据库
如何使用Spring Boot构建RESTful API,以在线图书管理系统为例
【10月更文挑战第9天】本文介绍了如何使用Spring Boot构建RESTful API,以在线图书管理系统为例,从项目搭建、实体类定义、数据访问层创建、业务逻辑处理到RESTful API的实现,详细展示了每个步骤。通过Spring Boot的简洁配置和强大功能,开发者可以高效地开发出功能完备、易于维护的Web应用。
30 3
|
3天前
|
监控 持续交付 API
深入理解微服务架构:构建高效、可扩展的系统
【10月更文挑战第14天】深入理解微服务架构:构建高效、可扩展的系统
17 0
|
10天前
|
消息中间件 监控 API
理解微服务架构:构建灵活和可扩展的应用
【10月更文挑战第7天】理解微服务架构:构建灵活和可扩展的应用
|
10天前
|
消息中间件 监控 API
深入理解微服务架构:构建可扩展与灵活的应用
【10月更文挑战第7天】深入理解微服务架构:构建可扩展与灵活的应用
24 0
|
5天前
|
文字识别 安全 Java
SpringBoot3.x和OCR构建车牌识别系统
本文介绍了一个基于Java SpringBoot3.x框架的车牌识别系统,详细阐述了系统的设计目标、需求分析及其实现过程。利用Tesseract OCR库和OpenCV库,实现了车牌图片的识别与处理,确保系统的高准确性和稳定性。文中还提供了具体的代码示例,展示了如何构建和优化车牌识别服务,以及如何处理特殊和异常车牌。通过实际应用案例,帮助读者理解和应用这一解决方案。
|
9天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用
【10月更文挑战第8天】本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,通过 Spring Initializr 创建并配置 Spring Boot 项目,实现后端 API 和安全配置。接着,使用 Ant Design Pro Vue 脚手架创建前端项目,配置动态路由和菜单,并创建相应的页面组件。最后,通过具体实践心得,分享了版本兼容性、安全性、性能调优等注意事项,帮助读者快速搭建高效且易维护的应用框架。
18 3
|
9天前
|
Kubernetes Cloud Native API
掌握Dapr:构建可移植的微服务应用
【10月更文挑战第8天】Dapr(Distributed Application Runtime)是一个开放、可移植的运行时环境,旨在简化微服务应用的构建。它通过提供一套API处理服务发现、状态管理、发布/订阅等常见问题,帮助开发者专注于业务逻辑。本文介绍Dapr的基本概念、核心组件、优势及实施步骤,适用于希望构建弹性、可扩展微服务应用的开发者。
|
10天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用
【10月更文挑战第7天】本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,通过 Spring Initializr 创建 Spring Boot 项目并配置 Spring Security。接着,实现后端 API 以提供菜单数据。在前端部分,使用 Ant Design Pro Vue 脚手架创建项目,并配置动态路由和菜单。最后,启动前后端服务,实现高效、美观且功能强大的应用框架。
13 2
|
9天前
|
消息中间件 存储 监控
探索微服务架构:构建可扩展的应用程序
【10月更文挑战第8天】探索微服务架构:构建可扩展的应用程序
19 0