【Java】Spring(Bean的生命周期)

发布于:2025-08-19 ⋅ 阅读:(15) ⋅ 点赞:(0)

        在 Spring 框架中,Bean 的生命周期管理是其核心功能之一。理解 Bean 的生命周期,对于开发者精准控制 Bean 的行为、优化资源管理以及排查问题至关重要。本文将深入剖析 Spring Bean 从创建到销毁的完整流程,结合代码示例和实际应用场景,带你掌握生命周期的关键节点与扩展技巧。

一、Bean 生命周期总览

Spring Bean 的生命周期可概括为 “创建 - 初始化 - 使用 - 销毁” 四大阶段,涉及多个扩展点(如接口回调、注解触发)。完整流程如下:

二、阶段详解与代码实践

1. 实例化(Instantiation)

作用:通过反射创建 Bean 的实例(调用构造方法)。
关键:此时仅完成对象创建,依赖注入和初始化尚未执行。

public class UserService {
    public UserService() {
        System.out.println("1. 实例化:调用构造方法");
    }
}

2. 依赖注入(Dependency Injection)

作用:Spring 容器将 Bean 依赖的其他对象(如 UserDao)注入到当前 Bean 中。
支持方式:构造器注入、Setter 注入、字段注入(@Autowired)。

public class UserService {
    @Autowired
    private UserDao userDao; // 依赖注入
    
    public UserService() {
        System.out.println("1. 实例化:调用构造方法");
    }
    
    // Setter 注入示例(可选)
    @Autowired
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
        System.out.println("2. 依赖注入:通过 Setter 注入 UserDao");
    }
}

3. Aware 接口回调(Optional)

Spring 提供 Aware 系列接口,让 Bean 主动获取容器信息(如 Bean 名称、应用上下文)。常见接口:

  • BeanNameAware:获取 Bean 在容器中的名称
  • BeanFactoryAware:获取 BeanFactory 容器
  • ApplicationContextAware:获取 ApplicationContext(更强大的容器上下文)
public class UserService implements BeanNameAware {
    private String beanName;
    
    @Override
    public void setBeanName(String name) {
        this.beanName = name;
        System.out.println("3. Aware 回调:Bean 名称为 " + beanName);
    }
}

4. BeanPostProcessor 前置处理

作用:全局拦截所有 Bean 的初始化流程,在初始化前修改 Bean 实例(如添加代理、修改属性)。
扩展点:实现 BeanPostProcessor 接口的 postProcessBeforeInitialization 方法。

@Component
public class LogBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("4. BeanPostProcessor 前置处理:" + beanName);
        return bean; // 返回修改后的 Bean(或原实例)
    }
}

5. 初始化阶段(Initialization)

初始化是 Bean 生命周期的核心扩展点,支持 三种方式(优先级:注解 > 接口 > XML 配置):

方式 1:@PostConstruct 注解(推荐)

作用:依赖注入完成后,自动触发标注方法(无需实现接口)

public class UserService {
    @PostConstruct
    public void initByAnnotation() {
        System.out.println("5. 初始化:@PostConstruct 触发");
    }
}
方式 2:InitializingBean 接口

作用:实现 afterPropertiesSet 方法,在依赖注入后执行初始化。

public class UserService implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("5. 初始化:InitializingBean 触发");
    }
}
方式 3:XML 配置 init-method

作用:在 XML 中指定初始化方法,与注解 / 接口方式兼容。

<bean id="userService" class="com.example.UserService" init-method="initByXml"/>
public class UserService {
    public void initByXml() {
        System.out.println("5. 初始化:XML init-method 触发");
    }
}

6. BeanPostProcessor 后置处理

作用:全局拦截 Bean 初始化流程,在初始化后修改 Bean(如 AOP 代理创建)。

@Component
public class AopBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("6. BeanPostProcessor 后置处理:" + beanName);
        // 此处可返回代理对象(如通过 Proxy.newProxyInstance 创建)
        return bean;
    }
}

7. Bean 就绪与使用

经过以上流程,Bean 已完成初始化,进入 “就绪状态”,可通过 getBean() 获取,或被其他 Bean 依赖使用。

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(App.class);
        UserService userService = context.getBean(UserService.class);
        System.out.println("7. Bean 就绪:" + userService);
    }
}

8. 销毁阶段(Destruction)

作用:容器关闭时,执行 Bean 的销毁逻辑(释放资源、关闭连接等)。支持 三种方式(优先级:注解 > 接口 > XML 配置):

方式 1:@PreDestroy 注解
public class UserService {
    @PreDestroy
    public void destroyByAnnotation() {
        System.out.println("8. 销毁:@PreDestroy 触发");
    }
}
方式 2:DisposableBean 接口
public class UserService implements DisposableBean {
    @Override
    public void destroy() throws Exception {
        System.out.println("8. 销毁:DisposableBean 触发");
    }
}
方式 3:XML 配置 destroy-method
<bean id="userService" class="com.example.UserService" destroy-method="destroyByXml"/>
public class UserService {
    public void destroyByXml() {
        System.out.println("8. 销毁:XML destroy-method 触发");
    }
}

三、常见问题与解决方案

1. 初始化方法不执行?

  • 检查是否开启注解支持:@ComponentScan 或 XML 中配置 <context:annotation-config/>
  • 确保 Bean 被 Spring 容器管理(加 @Component 或 XML 配置)。

2. BeanPostProcessor 不生效?

  • 确保实现类标注 @Component 或通过 XML 配置扫描。
  • BeanPostProcessor 是 全局生效 的,需注入到 Spring 容器中。

3. 原型 Bean 销毁方法不执行?

  • 原型 Bean 需手动调用 destroyBean 触发销毁,Spring 不自动管理。

四、总结

Spring Bean 的生命周期通过 “实例化、依赖注入、初始化、销毁” 四大阶段,结合丰富的扩展点(注解、接口、BeanPostProcessor),实现了灵活的 Bean 管理。


网站公告

今日签到

点亮在社区的每一天
去签到