Spring Bean的生命周期

一、BeanDefinition阶段(Bean还没出生)

Spring启动时第一件事不是创建对象,而是解析配置生成 BeanDefinition

BeanDefinition 本质就是:

Bean 的说明书
里面记录:

  • bean 的 class

  • scope(singleton / prototype)

  • 依赖关系

  • initMethod

  • destroyMethod

举个直觉例子:

1
2
3
UserService.class  
scope=singleton
init=initMethod

Spring 会把这些信息先放到 BeanDefinitionMap 里。

这一步其实就是:

扫描 → 解析 → 注册BeanDefinition

此时 对象还没创建


二、实例化 Bean(构造函数阶段)

接下来 Spring 才开始创建对象:

new UserService()

这个阶段只做一件事:

调用构造函数

所以如果你写:

1
2
3
public UserService() {  
System.out.println("constructor");
}

这里就会执行。

但注意一个关键点:

此时 依赖还没有注入

对象只是一个空壳。


三、依赖注入(DI)

接下来 Spring 会给 bean 填充依赖。

比如:

1
2
3
4
5
@Service  
public class OrderService {
@Autowired
private UserService userService;
}

Spring 会执行类似逻辑:

1
orderService.userService = userService

这一步叫:

populateBean

也就是:

属性填充

常见方式:

1
2
3
4
5
6
7
8
- @Autowired

- @Resource

- @Value

- setter 注入

到这里:

1
bean = 已创建 + 已注入依赖

四、Aware接口回调(获取Spring环境)

接下来 Spring 会检测 bean 是否实现了一些 Aware接口

如果实现了,就回调对应方法。

常见三个:

BeanNameAware

1
setBeanName(String name)

可以知道自己的 beanName。


BeanFactoryAware

1
setBeanFactory(BeanFactory factory)

可以拿到 BeanFactory。


ApplicationContextAware

1
setApplicationContext(ApplicationContext context)

可以拿到 Spring 上下文。

这一步本质是:

Spring 把自己的一些核心对象告诉 Bean


五、初始化阶段(重点)

初始化阶段其实分 三小步,但可以作为一个整体记。

顺序是:

1
2
3
4
5
BeanPostProcessor.before  

初始化方法

BeanPostProcessor.after

我们逐个看。


1 BeanPostProcessor before

Spring 会执行:

postProcessBeforeInitialization()

这是一个扩展点。

很多框架都会在这里做事。


2 初始化方法

有两种方式:

InitializingBean

afterPropertiesSet()

例如:

1
2
3
4
5
public class UserService implements InitializingBean {  
public void afterPropertiesSet() {
System.out.println("init");
}
}

自定义 init-method

@Bean(initMethod=”init”)

@PostConstruct

这一步通常用来:

  • 初始化资源

  • 建立连接

  • 校验配置


3 BeanPostProcessor after

接下来执行:

postProcessAfterInitialization()

这一步非常关键。

AOP 就是在这里发生的。


六、AOP代理创建(Spring最核心魔法)

postProcessAfterInitialization 阶段:

Spring 会检查:

这个 Bean 是否需要 AOP

比如:

  • @Transactional

  • @Async

  • @Cacheable

  • 自定义切面

如果需要,Spring不会直接返回原始对象,而是:

生成代理对象

代理类型有两种:

JDK 动态代理

条件:

bean 实现了接口

代理接口。


CGLIB

条件:

没有接口

Spring 会生成子类代理。


所以最终容器里的 bean 其实是:

代理对象

而不是原始对象。

这也是为什么:

AOP 本质 = 动态代理


七、Bean开始工作

到这里 Bean 生命周期就结束了。

之后应用运行时:

1
Controller → Service → DAO

调用的其实是:

代理对象

所以 AOP 才能拦截方法。


八、Bean销毁阶段(容器关闭)

当 Spring 容器关闭时,会执行销毁逻辑。

顺序:

1
2
3
4
5
@PreDestroy  

DisposableBean.destroy()

destroy-method

例如:
关闭数据库连接
释放资源