从 spring.factories
到 .imports
文件
在 Spring Boot 2.7 之前,自动配置类的注册是通过 META-INF/spring.factories
文件完成的,其中包含类似这样的条目:

为了提高性能、模块化和可读性,Spring Boot 2.7 引入了新的、专用的 .imports
文件机制来替代 spring.factories
中的自动配置注册。
org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件是一个纯文本文件,每行包含一个自动配置类的全限定类名(Fully Qualified Class Name) 。

- 每行一个类名。
- 支持注释 :以
#
开头的行被视为注释,可以用来说明或临时禁用某个配置。 - 语义清晰:文件名本身就说明了它的用途------注册自动配置导入。
工作原理
- 启动扫描 :当你的 Spring Boot 应用程序启动时,
SpringApplication
会扫描所有 classpath 下的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件。 - 读取类名:它会读取这些文件中的每一行,获取自动配置类的全限定名。
- 条件化加载 :对于每个列出的类,Spring Boot 会检查其上的条件注解(如
@ConditionalOnClass
,@ConditionalOnMissingBean
,@ConditionalOnProperty
等)。 - 注册 Bean :如果所有条件都满足,该自动配置类就会被加载,其中定义的
@Bean
方法会被执行,相关的组件(如数据源、模板引擎、安全配置等)就会自动注册到 Spring 应用上下文中。
SecurityAutoConfiguration
当我们引入了security相关依赖的时候,SecurityAutoConfiguration自动配置类开始发挥作用
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

ruby
@Import({ SpringBootWebSecurityConfiguration.class, SecurityDataConfiguration.class })
public class SecurityAutoConfiguration {
}
SecurityAutoConfiguration中引入了SpringBootWebSecurityConfiguration配置类
less
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
class SpringBootWebSecurityConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnDefaultWebSecurity
static class SecurityFilterChainConfiguration {
//配置默认的过滤器链条
@Bean
@Order(SecurityProperties.BASIC_AUTH_ORDER)
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((requests) -> requests.anyRequest().authenticated());
http.formLogin(withDefaults());
http.httpBasic(withDefaults());
return http.build();
}
}
// 启用@EnableWebSecurity注解
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(name = BeanIds.SPRING_SECURITY_FILTER_CHAIN)
@ConditionalOnClass(EnableWebSecurity.class)
@EnableWebSecurity
static class WebSecurityEnablerConfiguration {
}
}
SpringBootWebSecurityConfiguration做了两件事相对重要 一是创建了默认的过滤器链,二是使用了@EnableWebSecurity注解 这就是为什么我们只引入了jar包 springsecurity就可以通过默认的过滤器链来保护我们的资源,同时我们也可以看出开发者如果忘记了使用@EnableWebSecurity注解也没关系,框架会自动帮我们开启。
默认过滤器链
从上面的代码我们可以看出 SecurityFilterChainConfiguration将SecurityFilterChain实例注入到容器中,但前提是@ConditionalOnDefaultWebSecurity这个注解需要生效
css
@ConditionalOnDefaultWebSecurity
@ConditionalOnDefaultWebSecurity本质上是@Conditional注解
less
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(DefaultWebSecurityCondition.class)
public @interface ConditionalOnDefaultWebSecurity {
}
@Conditional(DefaultWebSecurityCondition.class) 这个是spring的条件化配置,意思是只有当 DefaultWebSecurityCondition
这个条件被判定为 true
时,被它标注的类或方法才应该被注册到 Spring 容器中(即生效);否则,就跳过它。
@Conditional注解要求传入一个实现了Condition接口的类作为参数,DefaultWebSecurityCondition实现了这个接口
- 在 Spring 应用上下文启动过程中,当遇到被
@Conditional
标注的元素时,Spring 会实例化你指定的Condition
类(这里是DefaultWebSecurityCondition
),并调用其matches()
方法。
java
@FunctionalInterface
public interface Condition {
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
这个类的主要作用是: 当内部类的所有的 .@Conditional 注解都成立的时候,才会注入该 Bean
scala
class DefaultWebSecurityCondition extends AllNestedConditions {
DefaultWebSecurityCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
// **作用**:`@ConditionalOnClass` 注解检查类路径(classpath)上是否存在指定的类。
//**逻辑**:只有当 `SecurityFilterChain.class` 和 `HttpSecurity.class` 这两个类**都存在于**类路径上时,这个条件才算通过
@ConditionalOnClass({ SecurityFilterChain.class, HttpSecurity.class })
static class Classes {
}
// 只有当当前 Spring 容器中**没有**类型为 `SecurityFilterChain` 的 Bean 时,这个条件才算通过
@ConditionalOnMissingBean({ SecurityFilterChain.class })
static class Beans {
}
}
所以springsecurity自动创建过滤器链的满足的条件是:1 类需要存在 2.用户没有手动的配置SecurityFilterChain。
目的 :这是实现"自定义优先 "(Opinionated Defaults)的关键。Spring Boot 的理念是,如果开发者没有进行任何安全配置,它就提供一个安全的默认配置(通常是一个简单的登录表单)。但如果开发者自己定义了一个 SecurityFilterChain
Bean 来配置自定义的安全规则(比如 OAuth2、JWT、特定的 URL 权限等),那么 Spring Boot 就应该自动禁用 其默认的安全配置,避免冲突。这个条件确保了只有在用户没有提供自己的安全配置时,才会应用默认配置
EnableWebSecurity
上面说自动配置类WebSecurityEnablerConfiguration帮我开启EnableWebSecurity注解, 但是有个前提是
@ConditionalOnMissingBean(name = BeanIds.SPRING_SECURITY_FILTER_CHAIN) @ConditionalOnClass(EnableWebSecurity.class) 这两个条件得同时生效 1是类路径中要存在EnableWebSecurity这个类 2是** Spring 容器中不存在名为 "springSecurityFilterChain"
的 Bean**
这么做的目的是:当 @EnableWebSecurity
注解被处理时,它会创建一个名为 springSecurityFilterChain
的 FilterChainProxy
Bean,这个 Bean 是整个 Spring Security 过滤器链的入口,如果用户正确地使用了 @EnableWebSecurity
@EnableWebSecurity
注解本身就会触发创建 springSecurityFilterChain
Bean。 同样,WebSecurityEnablerConfiguration
会因为该 Bean 已存在而被禁用,防止了 @EnableWebSecurity
被应用两次。