深入理解 Spring 核心概念

深入浅出 Spring 自动装配原理

@SpringBootApplication 作为入口,我们可以看到它包含三个核心注解:

1
2
3
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan

接下来详细解释每个注解的作用。

1. @SpringBootConfiguration

进入 @SpringBootConfiguration 后的内容如下:

1
2
3
4
5
6
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}

其实它只是声明 SpringApplication 也是一个配置类。


2. @ComponentScan

1
2
3
4
5
6
7
8
9
10
@AliasFor("value")
String[] basePackages() default {};

Class<?>[] basePackageClasses() default {}; // 以这个类为基准类

Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

boolean useDefaultFilters() default true;

@ComponentScan 的作用是扫描 Spring 默认的组件,比如 @Component@Service@Repository@Controller


3. @EnableAutoConfiguration

这是 Spring 自动装配的核心。它导入了一个类:

1
2
3
4
5
6
7
8
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

Class<?>[] exclude() default {};

String[] excludeName() default {};
}

深入 AutoConfigurationImportSelector

1
2
3
4
5
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}

自动配置的核心是从 classpath 中搜寻所有的 META-INF/spring.factories 配置文件,并加载其中的配置项为 @Configuration 的 JavaConfig 类。

spring.factories


Bean 的作用域

Bean Scope

1. singleton

  • 特点:容器中只存在一个共享实例,默认作用域。
  • 配置方式
1
<bean id="serviceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton" />

2. prototype

  • 特点:每次请求都会创建一个新的实例。
  • 配置方式
1
<bean id="account" class="com.foo.DefaultAccount" scope="prototype" />

3. request

  • 特点:每个 HTTP 请求对应一个实例,仅在 Web 环境下有效。
  • 配置方式
1
<bean id="loginAction" class="cn.csdn.LoginAction" scope="request" />

4. session

  • 特点:每个 HTTP Session 对应一个实例,仅在 Web 环境下有效。

Spring IOC 如何解决循环依赖

Spring 通过 三级缓存 解决单例模式下的循环依赖问题:

1
2
3
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); // 一级缓存
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); // 二级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); // 三级缓存

三级缓存的工作原理

  1. 一级缓存:存储完全初始化的 Bean。
  2. 二级缓存:存储早期暴露的 Bean(未完成属性赋值)。
  3. 三级缓存:存储 Bean 工厂,用于解决循环依赖。

示例

  • A 依赖 B,B 依赖 A。
  • A 初始化时,将自己暴露到三级缓存。
  • B 初始化时,从三级缓存获取 A 的早期引用,完成初始化。
  • 最终,A 和 B 都完成初始化并存入一级缓存。

Spring 中 Bean 的生命周期

Bean Lifecycle

生命周期流程

  1. 尝试从 Bean 工厂中获取 Bean
  2. 实例化 Bean:调用构造方法。
  3. 依赖注入:完成属性赋值。
  4. 调用 Aware 接口
    • BeanNameAware:传入 Bean 的 ID。
    • BeanClassLoaderAware:传入 ClassLoader 引用。
    • BeanFactoryAware:传入工厂实例。
  5. 调用 BeanPostProcessor
    • postProcessBeforeInitialization:AOP 切面逻辑。
  6. 初始化方法
    • 调用 InitializingBean.afterPropertiesSet()@PostConstruct
    • 调用配置的 init-method
  7. 调用 BeanPostProcessor
    • postProcessAfterInitialization
  8. 销毁方法
    • 调用 DisposableBean.destroy()@PreDestroy
    • 调用配置的 destroy-method

关键点总结

  1. Bean 自身方法:包括 init-methoddestroy-method
  2. Bean 级生命周期接口:如 BeanNameAwareInitializingBean
  3. 容器级生命周期接口:如 BeanPostProcessor
  4. 工厂后处理器接口:如 ConfigurationClassPostProcessor