一、Spring Boot的自动配置原理
Spring Boot使用一种称为“约定优于配置”的方法,这意味着如果你按照预定的方式来安排你的代码和依赖项,Spring Boot可以自动配置你的应用程序。主要特点包括:
- 自动检测:Spring Boot在应用启动时会自动检测添加到项目中的jar依赖,并基于这些依赖尝试推断需要配置哪些Bean。例如,如果Spring Boot检测到classpath中包含Spring Web MVC(通过spring-webmvc jar),它会自动配置你的应用程序为一个web应用,注册必要的Controller、ViewResolver等Bean。
- 自动配置:Spring Boot提供了大量的自动配置,这些配置尝试根据classpath下的库自动设置Spring应用。这包括内嵌服务器的配置、数据源、事务管理等。用户可以通过添加自定义属性来覆盖这些自动配置的默认设置
二、Spring Boot自动配置原理源码
SpringBoot的自动配置原理源码口是@SpringBootApplication注解,这个注解封装了3个注解
1.@SpringBootConfiguration
- 描述:这是一个特化的
@Configuration
注解,它标记了一个类作为Spring Boot应用的配置类。@Configuration
注解本身表明这个类可以使用Spring IoC容器作为bean定义的来源。
2. @ComponentScan
- 作用:这个注解告诉Spring从哪里开始扫描组件,所以它会自动发现和注册Spring容器中的bean。默认情况下,它会扫描
@SpringBootApplication
所在的包及其子包中的所有类。 - 用途:这允许开发者通过注解如
@Component
、@Service
、@Repository
和@Controller
等自动注册bean,无需显式书写bean的注册代码。
3. @EnableAutoConfiguration
- 重要性:这是Spring Boot的自动配置魔法所在。该注解利用Spring的条件注解(如
@Conditional
)来自动配置bean,假设根据类路径下的jar依赖、已定义的bean以及各种属性设置,条件成立的话。 - 实现机制:
@Import
注解:它导入AutoConfigurationImportSelector
,这个选择器通过读取META-INF/spring.factories
文件中的配置来自动选择配置类。这些配置类通常包括针对Spring Boot应用优化的自动配置类,这些类会配置如数据源、事务管理器、web配置等常见的功能。@AutoConfigurationPackage
:这个注解自动注册了配置类所在的包,这有助于确定需要自动配置的基本包。实际上,这个注解负责注册一个特殊的注册器,它会把主配置类(即@SpringBootApplication
所在的类)所在的包注册到Spring IoC容器中。
这个流程使得Spring Boot应用可以几乎不需要任何显式配置就快速启动和运行。通过这些自动配置的能力,开发者可以将更多的精力集中在业务逻辑上,而非配置上,大大提高了开发效率和应用的启动速度。这种设计也是Spring Boot广受欢迎的重要原因之一
三、如何覆盖默认的自动配置
虽然自动配置大大简化了应用的配置工作,但有时候你可能需要修改默认的行为或覆盖自动配置的一部分。你可以通过以下方式做到这一点:
-
指定属性:在
application.properties
或application.yml
中指定不同的属性值。 -
添加自定义
@Configuration
类:自定义配置类可以定义额外的bean或使用@Primary
注解覆盖自动配置的bean。- 你可以在你的启动类上使用
@ComponentScan
注解来指定Spring Boot扫描其他包。例如,如果你的启动类在com.example.demo
包中,而你想加载com.bite.autoconfig
包中的配置,你可以这样做:package com.example.demo;import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan;@SpringBootApplication @ComponentScan(basePackages = {"com.example.demo", "com.bite.autoconfig"}) public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);} }
- 你可以在你的启动类上使用
- 使用
@Import
注解:直接在你的配置类上使用@Import
来导入特定的配置类,这将覆盖自动配置。- 如果你知道具体的配置类,可以直接在启动类或任何配置类上使用
@Import
来显式地导入配置。这适用于需要导入具体配置类的场景:package com.example.demo;import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Import; import com.bite.autoconfig.BiteConfig;@SpringBootApplication @Import(BiteConfig.class) public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);} }
- 如果你知道具体的配置类,可以直接在启动类或任何配置类上使用
-
使用
@SpringBootApplication
的scanBasePackages
@SpringBootApplication
注解本身包含了@ComponentScan
的功能。因此,你也可以直接在这个注解中指定要扫描的包:
package com.example.demo;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication(scanBasePackages = {"com.example.demo", "com.bite.autoconfig"})
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}
-
处理第三方JAR包
- 对于第三方JAR包中的Bean,如果它们不是通过Spring的方式配置(比如使用Spring Boot的自动配置),你可能需要创建自己的配置类来实例化这些Bean。例如,如果一个第三方库提供了一个服务,你可以创建一个配置类,在那里创建一个Bean实例:
package com.example.demo.config;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import third.party.LibraryClass;@Configuration public class ThirdPartyConfig {@Beanpublic LibraryClass libraryClass() {return new LibraryClass();} }
- 对于第三方JAR包中的Bean,如果它们不是通过Spring的方式配置(比如使用Spring Boot的自动配置),你可能需要创建自己的配置类来实例化这些Bean。例如,如果一个第三方库提供了一个服务,你可以创建一个配置类,在那里创建一个Bean实例: