好问题,阿杰 👍
Spring Bean 的初始化过程是 Spring 框架最核心的机制之一,理解它能帮助你掌握依赖注入(DI)、AOP、生命周期回调等高级特性。
下面我给你讲一个完整、通俗又技术细节兼具的版本👇


🧩 一、整体流程概览

Spring Bean 的生命周期大体上可以分为 7 个阶段

1️⃣ 实例化(Instantiation)
2️⃣ 属性注入(Populate / Dependency Injection)
3️⃣ BeanNameAware / BeanFactoryAware 等回调
4️⃣ BeanPostProcessor 前置处理(postProcessBeforeInitialization)
5️⃣ 初始化(InitializingBean / @PostConstruct / init-method)
6️⃣ BeanPostProcessor 后置处理(postProcessAfterInitialization)
7️⃣ 使用与销毁(DisposableBean / @PreDestroy / destroy-method)


🧠 二、核心流程详解

1️⃣ 实例化(Instantiation)

Spring 通过 反射构造函数 创建 Bean 实例。
此时对象只是“空壳”,属性还没注入。

🔹 执行位置:

bean = createBeanInstance(beanDefinition);

🔹 示例:

public class UserService {
    public UserService() {
        System.out.println("1️⃣ 实例化 UserService");
    }
}


2️⃣ 属性注入(Populate Bean)

实例化后,Spring 会根据配置或注解(@Autowired, @Resource, XML 等)注入依赖对象。

🔹 执行位置:

populateBean(beanName, mbd, instanceWrapper);

🔹 示例:

public class UserController {
    @Autowired
    private UserService userService; // 此时被注入
}


3️⃣ Aware 接口回调

如果 Bean 实现了某些 “Aware 接口”,Spring 会将相关容器资源注入进来。

常见接口:

接口注入对象
BeanNameAware当前 Bean 的名称
BeanFactoryAwareBeanFactory 实例
ApplicationContextAwareApplicationContext 实例

🔹 示例:

public class MyBean implements BeanNameAware, ApplicationContextAware {
    public void setBeanName(String name) {
        System.out.println("3️⃣ BeanNameAware:" + name);
    }

    public void setApplicationContext(ApplicationContext ctx) {
        System.out.println("3️⃣ ApplicationContextAware 回调");
    }
}


4️⃣ BeanPostProcessor 前置处理

在初始化前,Spring 会调用 BeanPostProcessor 的:

postProcessBeforeInitialization(Object bean, String beanName)

允许你对 Bean 进行“加工”,比如 AOP 代理增强、属性修改等。

🔹 示例:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String name) {
        System.out.println("4️⃣ BeforeInit:" + name);
        return bean;
    }
}


5️⃣ 初始化(Initialization)

这是 Bean 真正“就绪”的阶段,可以通过三种方式实现初始化逻辑:

方式描述
@PostConstruct 注解推荐方式
实现 InitializingBean 接口旧式接口方式
在 XML 或 JavaConfig 中配置 init-method手动指定

🔹 示例:

@Component
public class MyService implements InitializingBean {
    @PostConstruct
    public void init1() { System.out.println("5️⃣ @PostConstruct 调用"); }

    @Override
    public void afterPropertiesSet() {
        System.out.println("5️⃣ InitializingBean.afterPropertiesSet()");
    }

    public void customInit() {
        System.out.println("5️⃣ init-method 调用");
    }
}

调用顺序通常是:

@PostConstruct → afterPropertiesSet() → init-method


6️⃣ BeanPostProcessor 后置处理

初始化完成后,再次执行:

postProcessAfterInitialization(Object bean, String beanName)

此时 Bean 已可用,AOP 代理、事务增强通常在此阶段生成。

🔹 示例:

public Object postProcessAfterInitialization(Object bean, String name) {
    System.out.println("6️⃣ AfterInit:" + name);
    return bean;
}


7️⃣ 使用与销毁

Bean 被使用中……(被依赖、被调用、被注入到控制器等)

当容器关闭时(如 context.close()),Spring 会执行销毁回调:

方式描述
@PreDestroy 注解推荐方式
实现 DisposableBean 接口旧式接口方式
XML 或 JavaConfig 中配置 destroy-method手动方式

🔹 示例:

@PreDestroy
public void preDestroy() { System.out.println("7️⃣ @PreDestroy 调用"); }

@Override
public void destroy() { System.out.println("7️⃣ DisposableBean.destroy()"); }

public void customDestroy() { System.out.println("7️⃣ destroy-method 调用"); }

调用顺序通常为:

@PreDestroy → destroy() → destroy-method


📊 三、完整调用顺序图

实例化 → 属性注入 → Aware 回调
     ↓
BeanPostProcessor.beforeInit()
     ↓
@PostConstruct / afterPropertiesSet() / init-method
     ↓
BeanPostProcessor.afterInit()
     ↓
Bean Ready
     ↓
@PreDestroy / destroy() / destroy-method


🧩 四、实用小结

环节常用注解/接口功能
初始化前BeanPostProcessor自定义初始化逻辑前处理
初始化@PostConstruct, InitializingBean初始化方法
初始化后BeanPostProcessor增强或AOP代理
销毁@PreDestroy, DisposableBean资源释放