Spring 基础
什么是 Spring
Spring 核心是提供了一个容器(Container),它们通常被称为 Spring 应用上下文,负责创建和管理应用的组件。这些组件就称为 bean。
Spring 技术的核心本质就是依赖注入、面向切面编程、自动装配等功能特性。
通过依赖注入将bean装配在一起,此时组件不再创建和管理它们所依赖的组件的生命周期,而是通过容器来管理所有的组件。
Spring Boot 是 Spring 的扩展,提供了许多生产方面的增强,最为熟知的就是自动配置(autoconfiguration)。涵盖了组件扫描(component scanning)和自动装配(autowiring)技术等。
配置
通常 Spring 通过自动配置技术会自动将 bean 装配在一起。只有在 Spring 不能自动配置组件的时候,才需要手动显示配置。
显示的配置有两种形式:
是基于 XML 文件的配置;
<beanid="service1"class="com.test.Service1" />
<beanid="service2"class="com.test.Service2">
<constructor-argref="service1" />
</bean>
是基于 Java 的配置。相对于 XML 形式的配置,基于 Java 的配置会带来多项额外的收益(包括更强的类型安全性以及更好的重构能力),因此也更多采用 Java 形式的配置。
@ConfigurationpublicclassServiceConfiguration {
@BeanpublicService1service1 () {
returnnewService1()
}
@BeanpublicService2service2 () {
returnService2(service1())
}
}该 Java 配置和上面的 XML 配置是等价的。
@Configuration 注解会告知 Spring 这是一个配置类,会为 Spring 应用上下文提供 bean。
@Bean 注解表明这些方法返回的对象会以 Bean 的形式添加到 Spring 的应用上下文中
初始构建规范
可以通过一些脚手架来自动生成简单的项目框架:
- Spring Tool Suite 创建新项目
- IntelliJ IDEA 创建新项目
初始 maven 构建规范
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-4.0.0.xsd"
>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath />
</parent>
<groupId>com.test</groupId>
<artifactId>hello-spring</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hello-spring</name>
<description>Spring Boot Demo</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<!-- 指定依赖作用的范围:test 表示只在测试时需要 -->
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
首先看 <parent> 元素,它表明当前工程所要引用的父工程信息。通过引用父工程可以实现以下几个功能:
- 统一jar包的版本:父工程的jar包版本可以被统一管理,这样在子工程中可以方便的引用,而不需要重复声明版本信息。
- 统一的依赖管理:父工程中声明的依赖可以直接被子工程继承,子工程不需要重复声明这些依赖
- 控制插件的版本:可以控制子工程中使用的插件的版本,确保整个项目使用同一版本的插件
- 聚合工程:父工程通过
<modules> 元素将多个子工程聚合在一起,便于统一管理和构建
这里表明我们的项目要以 spring-boot-starter-parent 作为父 POM(Project Object Model)。
然后看 <dependencies> 元素,它表明当前工程所需要的依赖项。它有以下几个作用:
- 声明项目依赖:声明项目所需要的库或组件,maven 构建时会下载相应的依赖。
- 版本管理:可以指定依赖项额版本号,减少版本冲突的风险
- 传递性依赖管理:如果项目依赖的库A又依赖了库B,那么maven会自动将库B加入到当前项目中。也可以通过配置排除某些传递性依赖。
- 范围管理:通过 scope 属性可以控制依赖作用的范围
- 优化构建:maven 根据 dependencies 信息构建项目的依赖树,自动下载、解析和管理这些依赖。
这些依赖可以是库、框架、组件或其他可重用的代码单元,他们以 JAR、WAR、EAR 或其他 maven 支持的打包类型提供。
spring boot starter 依赖特别之处就是,这些依赖本身并不包含库代码,而是传递性的拉取其他的库。
最后看 <build> 元素,它主要负责配置项目的构建设置,包括源代码的编译、测试的执行、资源的处理以及插件的配置等:
- 源代码目录配置:可以配置源代码(source)和测试代码(test source)的目录位置。maven 默认使用
src/main/java 为源代码目录;src/main/test 为测试代码目录。 - 输出目录配置:可以配置编译后的类文件(class files)和测试类文件的输出目录。默认将类文件输出到
target/classes 目录;测试类文件输出到 target/test-classes 目录。 - 插件配置:
<plugins> 子元素可以配置在构建声明周期中执行的插件。 - 资源处理:maven 的资源插件可以处理项目中的资源文件,如配置问价、属性文件等。通过 build 元素下的 resources 可以配置资源目录以及如何处理这些资源。
- 构建生命周期管理:虽然 build 元素本身并不直接代表 maven 的构建生命周期,但是它的插件和配置会影响到构建生命周期的执行。
这里引用了 spring-boot-maven-plugin 构建插件,它主要用于:1. 提供一个 maven goal 允许使用 maven 来运行应用。2. 将所有依赖的库打包到 JAR 中;3. 在 JAR 中生成一个 manifest 文件,将引导类声明为可执行 JAR 的主类。
引导应用
我们通常会通过可执行 JAR 文件的方式来运行应用,所以最重要的一点就是需要一个主类,它将在 JAR 运行的时候被执行。我们还需要一个最小化的 Spring 配置用来引导该应用,这就是 Application 类所要做的事情。
packagexxxxx;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
// spring boot 应用@SpringBootApplicationpublicclassXxxApplication {
publicstaticvoidmain (String[] args) {
// 运行应用SpringApplication.run(XxxApplication.class, args);
}
}@SpringBootApplication 注解表明这是一个 Spring Boot 应用,这是一个组合注解:
@SpringBootConfiguration - 将该类声明为配置类。@EnableAutoConfiguration - 启用 Spring Boot 的自动配置。@ComponentScan - 启用组件扫描,这样通过 @component、@controller 等注解声明的类,会自动注册到 Spring Boot 上下文中。
SpringApplication.run() 该方法真正的执行应用的引导过程,也就是创建 Spring 的应用上下文。
@Component 是一个非常基础和重要的注解,用于定义 Spring 容器管理的 Bean。当使用 @Component 注解标注一个类时,Spring 会自动检测这个类,通过自动装配来创建和管理该类的实例(即 Bean)。
@Component 注解的主要用途:
- Bean定义:使用
@Component 注解的类会被 Spring 识别为一个 Bean,从而可以在 Spring 容器中管理。 - 自动装配:可以被其他
Bean 使用 @Autowired 注解自动装配。 - 特殊化形式:用于表示特定类型的
Bean:
@Repository: 用于数据访问对象(DAO),通常与 JPA、Hibernate 等 ORM 框架一起使用@Service: 用于业务逻辑层,表示一个服务组件@Controller: 用于 MVC 的控制器组件,表示 Web 层的一个组件。
@Bean 也是 Spring 框架中用于定义和管理 Bean 的一个注解。它和 @Component 注解的区别
@Bean 用于标注在配置类的 方法 上,而 @Component 直接标注在一个类上。@Component 注解标注的类会被 Spring 自动扫描、创建和管理 Bean,而 @Bean 允许开发者通过编写自定义的逻辑来控制 Bean 的创建和初始化过程。
基本用法
@ConfigurationpublicclassAppConfig {
@BeanpublicMyServicemyService() {
returnnewMyServiceImpl();
} }@Bean 通常用在带有 @Configuration 注解类的方法上,并且该方法必须是公开的(public),并且不应该带有参数的(除非它们是被依赖的其他 Bean)。
Bean 的名称
@ConfigurationpublicclassAppConfig {
@Bean(name = "MyCustomBean")
publicMyServicemyService() {
returnnewMyServiceImpl();
}
// 或者使用多个别名@Bean(value = { "MyCustomBean1", "MyCustomBean2" })
publicMyServicemyService() {
returnnewMyServiceImpl();
}
}默认情况下 Bean 的名称和 方法名相同。可以通过 name 或 value 指定一个或多个别名。
依赖注入
@ConfigurationpublicclassAppConfig {
@BeanpublicMyServicemyService(OtherServiceotherService) {
MyServicemyService = newMyServiceImpl();
myService.doSomethingWidthOtherService(otherService);
returnmyService;
}
}@Bean 注解的方法可以有任意数量的参数,来表示构建该 bean 所需要的依赖,Spring 容器会自动将依赖 bean 注入到该方法中。
@Configuration 是 Spring 框架中的一个核心注解,它用于定义配置类,这些类可以代替传统的 XML 配置文件,使用 Java 代码配置 Spring 容器中的 Bean。
@Configuration 注解的主要用途:
- 定义配置类:标记该类是一个配置类,会被用来配置应用程序的上下文。
- 定义和管理 Bean:该类可以包含多个
@Bean 注解的方法,每个方法都会创建一个 Bean 并将其注册到 Spring 容器中。可以在应用程序的其他地方使用。 - 替代 XML 配置:使配置更加灵活和类型安全
- 支持组件扫描:可以与
@ComponentScan 一起使用,自动扫描并注册组件。 - 提供属性配置:还可以使用
@ConfigurationProperties 注解来提供应用程序的配置属性。并且允许将配置属性绑定到配置文件(例如 application.properties 或 application.yml)中的值
@ConfigurationProperties 注解是 Spring Boot 的一个核心注解,用于将配置文件中的属性绑定到 Java Bean 上,这种绑定方式比 Spring 的 @Value 注解更强大,更灵活。它可以将配置文件中的一组相关属性绑定到一个配置对象上,这个对象将作为 Bean 注册在 Spring 的应用上下文中。
@ConfigurationProperties(prefix = "my.app")
publicclassMyAppConfigProperties {
privateStringname;
// 可以添加检验@NotNullpublicStringgetName() {
returnname;
}
publicvoidsetName(Stringname) {
this.name = name;
}
}有两种主要方式来启用 @ConfigurationProperties 绑定的配置属性:
- 通过 @EnableConfigurationProperties 注解: 在配置类上使用
@EnableConfigurationProperties 注解并指定配置属性类的 Class 对象。这种方式通常用于你想要通过 @Bean 方法来提供配置属性实例时。
@Configuration@EnableConfigurationProperties({ MyAppConfigProperties.class })
publicclassMyAppConfig {
@BeanpublicMyAppConfigPropertiesmyAppConfigProperties() {
returnnewMyAppConfigProperties();
}
// 注意:在 Spring Boot 自动配置环境中,通常不需要显示定义这个 Bean// 因为 Spring Boot 会自动创建并注册它
}- 自动检测: 将
@ConfigurationProperties 注解添加在配置属性类上并且配合 @Component 注解一起使用,并确保它在 Spring Boot 组件扫描路径下,Spring Boot 会自动检测到它,并创建相应的 Bean。 - 和 @bean 注解一起使用: 一般情况下
@ConfigurationProperties 注解用于类上,但是他也可以用在使用 @Bean 注解的公共方法上,主要用于将属性绑定到第三方(在自己的控制范围之外的)组件上。
@SpringBootConfiguration 注解
该注解属于 Spring Boot 的注解,用于标记一个类作为配置类。它是 @Configuration 注解的派生注解,功能上和 @Configuration 注解保持一致。主要用于标记一个类是 Spring Boot 应用的配置类。
该注解一般不单独使用,而是直接使用 @SpringBootApplication 组合注解(@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan)来直接标注 Spring Boot 应用程序。
@EnableAutoConfiguration 注解
Spring Boot 通过 @EnableAutoConfiguration 注解开启自动配置功能,加载 spring.factories 文件中注册的各种 AutoConfiguration, 实例化该配置中定义的 Bean, 注入到 Spring 容器中。
- 需要和
@Configuration 注解配合使用 - 用于实例化依赖包中的对象
- 一般需要在
META-INF/spring.factories 文件中进行配置 - 经常用于自定义的 starter 中
主要用于加载 starter 目录包之外的,需要 Spring 自动生成 Bean 对象的,带有 @configuration 注解的类。一般用于对各种引入的 starter 依赖包指定的 (spring.factories) 类进行实例化。
@ComponentScan 注解通常和 @Configuration 注解一起使用,用于定义扫描包的规则。根据这些规则,Spring 会自动查找并装配标记了如 @Controller、@Service、@Repository、@Configuration 和 @Component 等注解的类到 Spring 容器中,供后续的依赖注入和管理。
通常 @ComponentScan 注解是和 @Configuration 注解一起使用的(也是最佳实践),但也有一些例外情况,参考:Must @ComponentScan be placed with @Configuration? (Spring Core)
@Configuration@ComponentScan(basePackages, basePackageClasses, includeFilters, excludeFilters)
publicclassAppConfig {
// 其他配置
}basePackages: 指定要扫描的基础包(及其子包)basePackageClasses: 指定用于派生基础包的类includeFilters 和 excludeFilters: 指定包含或排除特定类的规则
默认情况下,@ComponentScan 会扫描入口类同级及其子包下的所有的文件
@Autowired 是 Spring 框架提供的注解,用于自动装配(Autowiring)Bean。
字段注入
@ComponentpublicclassMyComponent {
@AutowiredprivateMyDependencymyDependency;
}这种方式最简单常用,但是不利于单元测试。会先通过反射调用无参构造函数来实例化对象,然后再通过反射获取属性上的 @Autowired 注解,根据类型或名称匹配依赖关系,最后将依赖注入到属性中
setter注入
@ComponentpublicclassMyComponent {
privateMyDependencymyDependency;
@AutowiredpublicvoidsetMyDependency(MyDependencymyDependency) {
this.myDependency = myDependency;
}
}它允许在对象创建后再进行注入,对于非必须得依赖项来说是有用的。
构造函数注入
@ComponentpublicclassMyComponent {
privatefinalMyDependencymyDependency;
@AutowiredpublicMyComponent (MyDependencymyDependency) {
this.myDependency = myDependency;
}
}这是推荐的注入方式,因为它确保了 Bean 在被使用之前就已经完全初始化了。如果只有一个构造函数的情况下,@Autowired注解 可以省略。
参考:As of Spring Framework 4.3, an @Autowired annotation on such a constructor is no longer necessary if the target bean only defines one constructor to begin with. However, if several constructors are available, at least one must be annotated to teach the container which one to use. 文档
@Resource 是 Java 提供的一个用于依赖注入的注解。作用和 @Autowired 注解一样。两者区别:
@Autowired 是 Spring 提供的注解,而 @Resource 是 Java EE 提供的注解。@Autowired 默认是按类型匹配注解的,而 @Resource 默认是按名称匹配注解的。@Autowired 可以直接标注在构造函数上,而 @Resource 需要标注在构造函数的参数上- 两者的属性设置也不同,
参考:
Spring 基础
什么是 Spring
Spring 核心是提供了一个容器(Container),它们通常被称为 Spring 应用上下文,负责创建和管理应用的组件。这些组件就称为
bean。Spring 技术的核心本质就是依赖注入、面向切面编程、自动装配等功能特性。
通过依赖注入将
bean装配在一起,此时组件不再创建和管理它们所依赖的组件的生命周期,而是通过容器来管理所有的组件。Spring Boot是Spring的扩展,提供了许多生产方面的增强,最为熟知的就是自动配置(autoconfiguration)。涵盖了组件扫描(component scanning)和自动装配(autowiring)技术等。配置
通常 Spring 通过自动配置技术会自动将
bean装配在一起。只有在Spring不能自动配置组件的时候,才需要手动显示配置。显示的配置有两种形式:
是基于 XML 文件的配置;
是基于 Java 的配置。相对于 XML 形式的配置,基于 Java 的配置会带来多项额外的收益(包括更强的类型安全性以及更好的重构能力),因此也更多采用 Java 形式的配置。
该 Java 配置和上面的 XML 配置是等价的。
@Configuration注解会告知 Spring 这是一个配置类,会为 Spring 应用上下文提供 bean。@Bean注解表明这些方法返回的对象会以 Bean 的形式添加到 Spring 的应用上下文中初始构建规范
可以通过一些脚手架来自动生成简单的项目框架:
初始 maven 构建规范
首先看
<parent>元素,它表明当前工程所要引用的父工程信息。通过引用父工程可以实现以下几个功能:<modules>元素将多个子工程聚合在一起,便于统一管理和构建这里表明我们的项目要以
spring-boot-starter-parent作为父 POM(Project Object Model)。然后看
<dependencies>元素,它表明当前工程所需要的依赖项。它有以下几个作用:这些依赖可以是库、框架、组件或其他可重用的代码单元,他们以 JAR、WAR、EAR 或其他 maven 支持的打包类型提供。
spring boot starter依赖特别之处就是,这些依赖本身并不包含库代码,而是传递性的拉取其他的库。最后看
<build>元素,它主要负责配置项目的构建设置,包括源代码的编译、测试的执行、资源的处理以及插件的配置等:src/main/java为源代码目录;src/main/test为测试代码目录。target/classes目录;测试类文件输出到target/test-classes目录。<plugins>子元素可以配置在构建声明周期中执行的插件。这里引用了
spring-boot-maven-plugin构建插件,它主要用于:1. 提供一个 maven goal 允许使用 maven 来运行应用。2. 将所有依赖的库打包到 JAR 中;3. 在 JAR 中生成一个 manifest 文件,将引导类声明为可执行 JAR 的主类。引导应用
我们通常会通过可执行 JAR 文件的方式来运行应用,所以最重要的一点就是需要一个主类,它将在 JAR 运行的时候被执行。我们还需要一个最小化的 Spring 配置用来引导该应用,这就是 Application 类所要做的事情。
@SpringBootApplication注解表明这是一个 Spring Boot 应用,这是一个组合注解:@SpringBootConfiguration- 将该类声明为配置类。@EnableAutoConfiguration- 启用 Spring Boot 的自动配置。@ComponentScan- 启用组件扫描,这样通过 @component、@controller 等注解声明的类,会自动注册到 Spring Boot 上下文中。SpringApplication.run()该方法真正的执行应用的引导过程,也就是创建 Spring 的应用上下文。@component 注解
@Component是一个非常基础和重要的注解,用于定义Spring容器管理的Bean。当使用@Component注解标注一个类时,Spring会自动检测这个类,通过自动装配来创建和管理该类的实例(即Bean)。@Component注解的主要用途:@Component注解的类会被Spring识别为一个Bean,从而可以在Spring容器中管理。Bean使用@Autowired注解自动装配。Bean:@Repository: 用于数据访问对象(DAO),通常与 JPA、Hibernate 等 ORM 框架一起使用@Service: 用于业务逻辑层,表示一个服务组件@Controller: 用于 MVC 的控制器组件,表示 Web 层的一个组件。@bean 注解
@Bean也是Spring框架中用于定义和管理Bean的一个注解。它和@Component注解的区别@Bean用于标注在配置类的 方法 上,而@Component直接标注在一个类上。@Component注解标注的类会被Spring自动扫描、创建和管理Bean,而@Bean允许开发者通过编写自定义的逻辑来控制Bean的创建和初始化过程。基本用法
@Bean通常用在带有@Configuration注解类的方法上,并且该方法必须是公开的(public),并且不应该带有参数的(除非它们是被依赖的其他Bean)。Bean 的名称
默认情况下
Bean的名称和 方法名相同。可以通过name或value指定一个或多个别名。依赖注入
@Bean注解的方法可以有任意数量的参数,来表示构建该bean所需要的依赖,Spring容器会自动将依赖bean注入到该方法中。@configuration 注解
@Configuration是Spring框架中的一个核心注解,它用于定义配置类,这些类可以代替传统的XML配置文件,使用Java代码配置Spring容器中的Bean。@Configuration注解的主要用途:@Bean注解的方法,每个方法都会创建一个Bean并将其注册到Spring容器中。可以在应用程序的其他地方使用。@ComponentScan一起使用,自动扫描并注册组件。@ConfigurationProperties注解来提供应用程序的配置属性。并且允许将配置属性绑定到配置文件(例如 application.properties 或 application.yml)中的值@ConfigurationProperties 注解
@ConfigurationProperties注解是Spring Boot的一个核心注解,用于将配置文件中的属性绑定到Java Bean上,这种绑定方式比Spring的@Value注解更强大,更灵活。它可以将配置文件中的一组相关属性绑定到一个配置对象上,这个对象将作为Bean注册在Spring的应用上下文中。有两种主要方式来启用
@ConfigurationProperties绑定的配置属性:@EnableConfigurationProperties注解并指定配置属性类的Class对象。这种方式通常用于你想要通过@Bean方法来提供配置属性实例时。@ConfigurationProperties注解添加在配置属性类上并且配合@Component注解一起使用,并确保它在Spring Boot组件扫描路径下,Spring Boot会自动检测到它,并创建相应的Bean。@ConfigurationProperties注解用于类上,但是他也可以用在使用@Bean注解的公共方法上,主要用于将属性绑定到第三方(在自己的控制范围之外的)组件上。@SpringBootConfiguration 注解
该注解属于
Spring Boot的注解,用于标记一个类作为配置类。它是@Configuration注解的派生注解,功能上和@Configuration注解保持一致。主要用于标记一个类是Spring Boot应用的配置类。该注解一般不单独使用,而是直接使用
@SpringBootApplication组合注解(@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan)来直接标注Spring Boot应用程序。@EnableAutoConfiguration 注解
Spring Boot通过@EnableAutoConfiguration注解开启自动配置功能,加载spring.factories文件中注册的各种AutoConfiguration, 实例化该配置中定义的Bean, 注入到 Spring 容器中。@Configuration注解配合使用META-INF/spring.factories文件中进行配置主要用于加载 starter 目录包之外的,需要 Spring 自动生成 Bean 对象的,带有 @configuration 注解的类。一般用于对各种引入的 starter 依赖包指定的 (spring.factories) 类进行实例化。
@componentscan 注解
@ComponentScan注解通常和@Configuration注解一起使用,用于定义扫描包的规则。根据这些规则,Spring会自动查找并装配标记了如@Controller、@Service、@Repository、@Configuration和@Component等注解的类到Spring容器中,供后续的依赖注入和管理。basePackages: 指定要扫描的基础包(及其子包)basePackageClasses: 指定用于派生基础包的类includeFilters和excludeFilters: 指定包含或排除特定类的规则默认情况下,
@ComponentScan会扫描入口类同级及其子包下的所有的文件@Autowired 注解
@Autowired是Spring框架提供的注解,用于自动装配(Autowiring)Bean。字段注入
这种方式最简单常用,但是不利于单元测试。会先通过反射调用无参构造函数来实例化对象,然后再通过反射获取属性上的 @Autowired 注解,根据类型或名称匹配依赖关系,最后将依赖注入到属性中
setter注入
它允许在对象创建后再进行注入,对于非必须得依赖项来说是有用的。
构造函数注入
这是推荐的注入方式,因为它确保了
Bean在被使用之前就已经完全初始化了。如果只有一个构造函数的情况下,@Autowired注解 可以省略。@resource 注解
@Resource是Java提供的一个用于依赖注入的注解。作用和@Autowired注解一样。两者区别:@Autowired是Spring提供的注解,而@Resource是Java EE提供的注解。@Autowired默认是按类型匹配注解的,而@Resource默认是按名称匹配注解的。@Autowired可以直接标注在构造函数上,而@Resource需要标注在构造函数的参数上参考: