在 Huazie 的上篇博文中,我们详细了解了关于 @SpringBootApplication 注解的一些内容,文章最后提到了 @EnableAutoConfiguration
注解,用来开启 Spring Boot
的自动配置功能,这将是本篇将要重点讲解的内容。
我们知道,在没有使用 Spring Boot
的情况下,Bean
的生命周期都是由 Spring
来管理的,并且 Spring
是无法自动配置 @Configuration
注解的类。Spring Boot
的核心功能之一就是根据约定自动管理 @Configuration
注解的类 ,其中 @EnableAutoConfiguration
注解就是实现该功能的组件之一。
@EnableAutoConfiguration
注解 位于 spring-boot-autoconfigure
包内,当使用 @SpringBootApplication
注解时,它也就会自动生效。
结合上面的内容,我们很容易猜到 @EnableAutoConfiguration
注解是用来启动 Spring
应用程序上下文时进行自动配置,它会尝试猜测和配置项目可能需要的 Bean
。
自动配置通常是根据项目中引入的类和已定义的 Bean
来实现的。在自动配置过程中,会检查项目的classpath
(类路径)中引入的类以及项目依赖的 jar
包中的组件。
下面我们来看看,常见的自动配置的示例,如下所示:
Spring Boot
的 JDBC Starter
依赖,它会根据类路径中的相关库(如 HikariCP、Durid、Tomcat JDBC
等)自动配置数据库连接池。我们只需在配置文件中提供数据库连接的信息,Spring Boot
将会自动创建并配置连接池。Spring Boot
的 Web Starter
依赖时,它会自动配置嵌入式的 Web
服务器(如 Tomcat、Jetty、 Undertow
等),并为我们提供默认的 Web
应用程序上下文和基本的 Web
配置,例如 Servlet、Filter、Listener
等。Spring MVC
的相关依赖,Spring Boot
会自动配置 基于注解的控制器、视图解析器、异常处理 等,使得开发 Web
应用变得更加简单。Hibernate、MyBatis
等)的相关依赖时,Spring Boot
会自动配置相应的 SessionFactory
、事务管理器 等组件,以帮助你进行数据库操作。Spring Security
的相关依赖时,Spring Boot
会自动配置基本的 安全过滤器链、用户认证和授权 等,提供基本的应用程序安全性。下面我们来看看 @EnableAutoConfiguration
注解的源码【版本:2.7.9】:
/**
* 启用Spring应用程序上下文的自动配置,尝试猜测和配置可能需要的Bean。
* 自动配置类通常基于你的类路径和你已定义的Bean来应用。
* 例如,如果你在类路径中引入了tomcat-embedded.jar,那么很可能希望有一个
* TomcatServletWebServerFactory(除非你已经定义了自己的ServletWebServerFactory Bean)。
*
* 当使用@SpringBootApplication注解时,上下文的自动配置会自动启用,因此添加此注解没有额外的效果。
*
* 自动配置试图尽可能智能,并且随着你定义更多自己的配置而退避。
* 你可以手动使用exclude()方法排除任何你不想应用的配置(如果无法访问它们,
* 则可以使用excludeName()方法)。你还可以通过spring.autoconfigure.exclude属性来排除它们。
* 自动配置总是在用户自定义的Bean注册之后应用。
*
* 使用@EnableAutoConfiguration注解标注的类所在的包通常具有特殊意义,并且经常被用作"默认"。
* 例如,在扫描@Entity类时将使用该包。通常建议将@EnableAutoConfiguration(如果你没有使用
* @SpringBootApplication)放在根包中,以便可以搜索所有子包和类。
*
* 自动配置类是常规的Spring @Configuration Bean。它们是通过ImportCandidates 和
* SpringFactoriesLoader 机制(针对这个类进行索引)来定位的。通常,自动配置Bean是
* @Conditional Bean(通常使用@ConditionalOnClass和@ConditionalOnMissingBean注解)。
*
* @author Phillip Webb
* @author Stephane Nicoll
* @since 1.0.0
* @see ConditionalOnBean
* @see ConditionalOnMissingBean
* @see ConditionalOnClass
* @see AutoConfigureAfter
* @see SpringBootApplication
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
/**
* 可以用于覆盖自动配置是否启用的环境属性
*/
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
/**
* 排除特定的自动配置类,以使它们永远不会应用
* @return 要排除的类
*/
Class<?>[] exclude() default {};
/**
* 排除特定的自动配置类名,以使它们永远不会应用
* @return 要排除的类名
* @since 1.3.0
*/
String[] excludeName() default {};
}
通过查看源码,我们可以看到 @EnableAutoConfiguration
注解提供了一个常量 和 两个成员变量:
ENABLED_OVERRIDE_PROPERTY
: 用于覆盖自动配置是否启用的环境属性exclude
:排除特定的自动配置类excludeName
:排除特定的自动配置类名正如前面所说, @EnableAutoConfiguration
会尝试猜测并配置你可能需要的 Bean
,但实际情况如果是我们不需要这些预配置的 Bean
,那么也可以通过它的两个成员变量 exclude
和 excludeName
来排除指定的自动配置。
// 通过 @SpringBootApplication 排除 DataSourceAutoConfiguration
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class DemoApplication {
}
或者:
// 通过 @EnableAutoConfiguration 排除 DataSourceAutoConfiguration
@Configuration
@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)
public class DemoConfiguration {
}
注意:
Spring Boot
在进行实体类扫描时,会从@EnableAutoConfiguration
注解标注的类所在的包开始扫描。这也是在使用@SpringBootApplication
注解时需要将被注解的类放在顶级package
下的原因,如果放在较低层级,它所在package
的同级或上级中的类就无法被扫描到,从而无法正常使用相关注解(如@Entity
)。
从我们上篇博文中新建的 Spring Boot 项目可知,@SpringBootApplication
注解通常用于标记 Spring Boot
应用程序的入口类。它会自动启用 Spring Boot
的自动配置和组件扫描等功能。但是,如果你希望将自动配置应用于其他类,而不是入口类本身,那么你可以将 @SpringBootApplication
注解添加到这些类上。同样地,@EnableAutoConfiguration
注解也可以用于其他类,而不仅限于入口类。这个注解用于启用Spring
的自动配置功能,并根据类路径和已定义的Bean来自动配置应用程序上下文。
因此,在 Spring Boot
应用程序中,入口类只是一个用来引导应用程序的类,而真正的自动配置和功能开启是通过 @SpringBootApplication
和 @EnableAutoConfiguration
注解所用的其他类完成的。
从上面 @EnableAutoConfiguration
注解的源码可知,@Import(AutoConfigurationImportSelector.class)
也是@EnableAutoConfiguration
注解的组成部分,这也是自动配置功能的核心实现者。
下面我们重点讲解一下 @Import
注解,至于它对应的 ImportSelector
,我们将在后续的博文中详细介绍。
@Import
注解位于 spring-context
项目内,主要提供导入配置类的功能。在后续的学习源码的过程中,我们会发现有大量的 EnableXXX
类使用了@Import
注解。
下面我们来看一下 @Import
的源码【版本 spring-context-5.3.25】:
/**
* 指示导入一个或多个组件类,通常是@Configuration类。
*
* 提供与Spring XML中的<import/>元素相当的功能。允许导入@Configuration类、
* ImportSelector 和 ImportBeanDefinitionRegistrar 实现,以及普通的组件类
* (从4.2开始;类似于AnnotationConfigApplicationContext.register)。
*
* 在导入的 @Configuration 类中声明的@Bean定义应该通过@Autowired注入来访问。
* 可以将bean本身进行自动装配,也可以将声明bean的配置类实例进行自动装配。
* 后一种方法允许在@Configuration类方法之间进行显式且友好的导航(适用于IDE)。
*
* 可以在类级别或作为元注解进行声明。
*
* 如果需要导入XML或其他非 @Configuration 的bean定义资源,请使用 @ImportResource 注解来实现。
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.0
* @see Configuration
* @see ImportSelector
* @see ImportBeanDefinitionRegistrar
* @see ImportResource
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* @Configuration、ImportSelector、ImportBeanDefinitionRegistrar 或常规组件类可以用来进行导入。
*/
Class<?>[] value();
}
上面的源码注释中,已经将 @Import
注解上的英文注释翻译成了中文注释,大家可以阅读了解下,这里就不再展开介绍了。
细心的朋友可能发现了,在 @EnableAutoConfiguration
注解的源码中,还有一个 @AutoConfigurationPackage
注解。
那么 @AutoConfigurationPackage
注解有啥作用呢?
在解答之前,我们先来看看 @AutoConfigurationPackage 注解的源码【版本 2.7.9 】:
/**
* 将包注册到 AutoConfigurationPackages 中。
* 当没有指定基础包或基础包类时,将会注册带有注解类的包。
*
* @author Phillip Webb
* @since 1.3.0
* @see AutoConfigurationPackages
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
/**
* 应该注册到 AutoConfigurationPackages 的基础包。
* 使用 basePackageClasses 作为基于类型安全的替代方法,而不是基于字符串的包名。
*
* @since 2.3.0
*/
String[] basePackages() default {};
/**
* @AutoConfigurationPackage 提供了一种类型安全的替代方案,用于指定要注册到 AutoConfigurationPackages 的包。
* 考虑在每个包中创建一个特殊的无操作标记类或接口,除了被此属性引用外,不具备任何其他功能。
*
* @since 2.3.0
*/
Class<?>[] basePackageClasses() default {};
}
通过上述阅读源码,我们可以看到 @AutoConfigurationPackage
上有如下这段代码:
@Import(AutoConfigurationPackages.Registrar.class)
通过上面的 @Import
注解介绍,我们可以知道,这段代码的作用其实就是通过导入AutoConfigurationPackages.Registrar
类【其中 ImportBeanDefinitionRegistrar
用于存储导入配置的基础包信息】,将基础包及其子包注册到 AutoConfigurationPackages
中,以便实现自动配置的功能。
通常情况下,Spring Boot
应用程序会将主配置类(例如使用 @SpringBootApplication
注解的类)置于根包中。这样做的话,根包会作为默认的扫描路径,用于自动发现和注册 Spring
组件(如@Controller、@Service、@Repository
等)。
当使用 @AutoConfigurationPackage
注解时,它会将指定类所在的包及其子包中的组件自动注册到Spring应用程序上下文中,即自动装配这些组件,从而简化了组件的配置和使用。
本篇笔者介绍了 @EnableAutoConfiguration
注解的相关功能,当然其中真正实现自动配置功能的核心实现者 AutoConfigurationImportSelector
还没有详细说明,那下一篇博文我们将重点对 AutoConfigurationImportSelector
的源码进行学习,敬请期待!!!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。