Spring中Bean的生命周期

在 Spring IoC 容器中,Bean 的生命周期是一个非常重要的概念,它定义了 Bean 从创建到销毁的完整过程。了解这一过程有助于开发者在合适的阶段对 Bean 进行定制化处理(如初始化资源、销毁资源等)。以下是 Bean 生命周期的详细流程及关键阶段说明:

一、Bean 生命周期的完整流程

1. 容器启动与 Bean 定义加载
  • 阶段说明:Spring 容器启动时,会解析配置文件(如 XML)或注解(如 @Configuration),加载 Bean 的定义信息(如类名、属性值、依赖关系等)。
  • 关键动作
    • 容器读取 BeanDefinition( Bean 的元数据描述)。
    • 注册 Bean 到容器的注册表中。
2. Bean 实例化(Instantiation)
  • 阶段说明:容器根据 BeanDefinition 创建 Bean 实例。
  • 实例化方式
    • 构造函数实例化:通过无参构造函数或指定构造函数创建对象(如 @Bean 注解或 XML 中 <constructor-arg>)。
    • 工厂方法实例化:调用静态工厂方法或实例工厂方法创建对象(如 factory-method 属性)。
  • 示例
    // 构造函数实例化
    public class UserService {
        public UserService() { System.out.println("UserService 实例化"); }
    }
    
    // 工厂方法实例化
    public class BeanFactory {
        public static UserService createService() {
            return new UserService();
        }
    }
    
3. 属性填充(Population of Properties)
  • 阶段说明:为 Bean 的属性设置值或注入依赖对象。
  • 依赖注入方式
    • setter 注入:通过 setter 方法注入(如 XML 中 <property>@Autowired 注解在 setter 上)。
    • 构造器注入:通过构造函数参数注入(如 @Autowired 注解在构造函数上)。
    • 字段注入:直接在字段上使用 @Autowired 等注解注入。
  • 示例
    public class UserService {
        private UserRepository userRepository;
        
        // 构造器注入
        @Autowired
        public UserService(UserRepository userRepository) {
            this.userRepository = userRepository;
        }
    }
    
4. 初始化前处理(Post Process Before Initialization)
  • 阶段说明:在 Bean 初始化前,执行 BeanPostProcessorpostProcessBeforeInitialization 方法。
  • 作用:可用于修改 Bean 的属性值,或在初始化前对 Bean 进行增强(如 AOP 代理生成)。
  • 示例
    public class MyBeanPostProcessor implements BeanPostProcessor {
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) {
            if (bean instanceof UserService) {
                System.out.println("初始化前处理:" + beanName);
            }
            return bean;
        }
    }
    
5. 初始化(Initialization)
  • 阶段说明:调用 Bean 的初始化方法,完成资源加载、配置初始化等操作。
  • 初始化方式
    • 实现 InitializingBean 接口:重写 afterPropertiesSet() 方法。
    • 使用 @PostConstruct 注解:标注在方法上(JSR-250 规范)。
    • 在 XML 中配置 init-method:指定初始化方法名。
  • 示例
    public class UserService implements InitializingBean {
        @PostConstruct
        public void init1() {
            System.out.println("@PostConstruct 初始化");
        }
        
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("InitializingBean 初始化");
        }
        
        public void init2() {
            System.out.println("init-method 初始化");
        }
    }
    
    执行顺序@PostConstruct > InitializingBean.afterPropertiesSet() > init-method
6. 初始化后处理(Post Process After Initialization)
  • 阶段说明:在 Bean 初始化后,执行 BeanPostProcessorpostProcessAfterInitialization 方法。
  • 作用:常用于完成 AOP 代理的最终包装,或对 Bean 进行最后的增强处理。
  • 示例
    public class MyBeanPostProcessor implements BeanPostProcessor {
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) {
            if (bean instanceof UserService) {
                System.out.println("初始化后处理:" + beanName);
            }
            return bean;
        }
    }
    
7. Bean 就绪(Ready for Use)
  • 阶段说明:Bean 已完全初始化,可被容器中的其他组件调用。
  • 应用场景:如 Web 层调用 Service 层 Bean,Service 层调用 Repository 层 Bean 等。
8. 销毁前处理(Pre-Destruction)
  • 阶段说明:当容器关闭时,在 Bean 销毁前执行相关操作。
  • 销毁方式
    • 实现 DisposableBean 接口:重写 destroy() 方法。
    • 使用 @PreDestroy 注解:标注在方法上(JSR-250 规范)。
    • 在 XML 中配置 destroy-method:指定销毁方法名。
  • 示例
    public class UserService implements DisposableBean {
        @PreDestroy
        public void destroy1() {
            System.out.println("@PreDestroy 销毁前处理");
        }
        
        @Override
        public void destroy() throws Exception {
            System.out.println("DisposableBean 销毁");
        }
        
        public void destroy2() {
            System.out.println("destroy-method 销毁");
        }
    }
    
    执行顺序@PreDestroy > DisposableBean.destroy() > destroy-method
9. 销毁(Destruction)
  • 阶段说明:Bean 被销毁,释放占用的资源(如数据库连接、文件句柄等)。
  • 触发时机
    • 手动关闭容器(如 context.close())。
    • 应用程序正常退出或异常终止。

二、Bean 生命周期关键接口与注解总结

阶段接口/注解示例方法执行时机
初始化前BeanPostProcessorpostProcessBeforeInitializationBean 初始化前
初始化InitializingBeanafterPropertiesSet属性填充后,初始化方法前
初始化@PostConstruct自定义方法属性填充后,InitializingBean
初始化init-method自定义方法InitializingBean
初始化后BeanPostProcessorpostProcessAfterInitialization初始化方法后
销毁前DisposableBeandestroy容器关闭时,销毁方法前
销毁前@PreDestroy自定义方法DisposableBean
销毁前destroy-method自定义方法DisposableBean

三、Bean 生命周期流程图

容器启动,加载Bean定义 --------------------→
↓
实例化Bean(通过构造函数或工厂方法)------→
↓
填充Bean属性(依赖注入)------------------→
↓
调用BeanPostProcessor.postProcessBeforeInitialization →
↓
调用初始化方法(@PostConstruct/InitializingBean/init-method)→
↓
调用BeanPostProcessor.postProcessAfterInitialization →
↓
Bean就绪,可被使用 ----------------------→
↓
容器关闭时,调用@PreDestroy/DisposableBean/destroy-method →
↓
Bean销毁,释放资源 ----------------------→

四、典型应用场景

  1. 资源初始化与释放

    • 在初始化方法中连接数据库、加载配置文件。
    • 在销毁方法中关闭数据库连接、释放线程池资源。
  2. AOP 代理生成

    • BeanPostProcessor 在初始化后处理阶段生成代理对象(如 AnnotationAwareAspectJAutoProxyCreator)。
  3. 动态属性修改

    • 通过 BeanPostProcessor 在初始化前后修改 Bean 的属性值(如加密配置项)。

五、注意事项

  • 单例与原型 Bean 的区别
    • 单例 Bean:生命周期与容器一致,容器关闭时销毁。
    • 原型 Bean:每次获取时创建新实例,容器不管理其销毁(需手动释放资源)。
  • 初始化与销毁方法的异常处理
    • 初始化方法抛出异常会导致容器启动失败。
    • 销毁方法抛出异常会被日志记录,但不影响容器关闭。
  • 注解与接口的优先级
    • @PostConstruct@PreDestroy 优于接口实现(基于 JSR 规范,更通用)。

通过掌握 Bean 的生命周期,开发者可以更精准地控制 Bean 的行为,实现复杂的初始化逻辑和资源管理,提升 Spring 应用的健壮性和灵活性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值