spring注解开发——说说bean的生命周期

本文深入探讨了Spring框架中Bean的生命周期,包括单例和多例模式下Bean的创建、初始化和销毁过程。通过实例演示了如何利用@Scope、@Bean、InitializingBean、DisposableBean、@PostConstruct和@PreDestroy等注解和接口来控制Bean的生命周期。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说说Bean的生命周期

bean的生命周期大家可能都知道,我这里主要说说在bean生命周期的各个阶段我们可以做些什么

  • @Bean单例模式下

    这里我们定义一个ColorRed类作为简单的bean,在类中增加两个方法,init()作为初始化bean时调用,destroy()作为销毁bean时调用

    public class ColorRed {
    
        public ColorRed() {
            System.out.println("===> colorRed bean created...");
        }
    
        public void init() {
            System.out.println("===> colorRed bean init...");
        }
    
        public void destroy() {
            System.out.println("===> colorRed bean destroy...");
        }
    }
    

    注入IOC容器:在注入时我们指定bean初始化和销毁时调用的方法

    @Configuration
    public class AnnotationContextConfig {
    	// @Scope("prototype")
        @Bean(initMethod = "init", destroyMethod = "destroy")
        public ColorRed colorRed() {
    
            return new ColorRed();
        }
    }
    

    测试:

    public class BeanLifeCycleTest {
    
        @Test
        public void testAnnotationBean() {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationContextConfig.class);
            System.out.println("===> Ioc container created...");
    
            applicationContext.close();
        }
    }
    

    看下结果:我们可以看到单例bean在IOC容器创建的时候就会创建,并且初始化,在容器关闭的时候bean会被销毁

    ===> colorRed bean created...
    ===> colorRed bean init...
    ===> Ioc container created...
    ===> colorRed bean destroy...
    
  • @Bean多例模式

    在配置文件中将bean上的@Scope(“prototype”)注释打开,由于多例模式下获取bean的时候bean才会被创建,所以测试方法增加如下:

    public class BeanLifeCycleTest {
    
        @Test
        public void testAnnotationBean() {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationContextConfig.class);
            System.out.println("===> Ioc container created...");
    
            ColorRed bean1 = applicationContext.getBean(ColorRed.class);
            ColorRed bean2 = applicationContext.getBean(ColorRed.class);
    
            System.out.println(bean1 ==  bean2);
    
            applicationContext.close();
        }
    }
    

    结果:可以看到获取两次bean,调用了两次初始化方法,但是,关闭容器的时候并没有调用我们在@bean里面设置的销毁方法destroyMethod = “destroy”,也就是说多例模式下容器只管创建初始化bean,而不会去销毁bean

    ===> Ioc container created...
    ===> colorRed bean created...
    ===> colorRed bean init...
    ===> colorRed bean created...
    ===> colorRed bean init...
    false
    
  • 使用接口InitializingBean,DisposableBean,我们新建一个bean,实现这两个接口:

    public class ColorGreen implements InitializingBean, DisposableBean {
    
        public ColorGreen() {
            System.out.println("===> colorGreen bean created...");
        }
    
        @Override
        public void destroy() throws Exception {
            System.out.println("===> colorGreen bean destroyed...");
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("===> colorGreen bean initializing...");
        }
    }
    

    可以看到InitializingBean有个afterPropertiesSet()方法,在bean创建并且都赋值好后会被调用,DisposableBean有个destroy()方法,在bean销毁的时候会被调用。单例模式下和@Bean注解一样,我们看看多例模式

    注册bean:

    @Scope("prototype")
    @Bean
    public ColorGreen colorGreen() {
        return new ColorGreen();
    }
    

    测试方法:

    @Test
        public void testInterfaceBean() {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationContextConfig.class);
            System.out.println("===> Ioc container created...");
    
            ColorGreen bean = applicationContext.getBean(ColorGreen.class);
            ColorGreen bean2 = applicationContext.getBean(ColorGreen.class);
    
            applicationContext.close();
        }
    

    打印结果:不好意思,还是和@bean一样,多例模式下spring只管创建,不管销毁。。。

    ===> Ioc container created...
    ===> colorGreen bean created...
    ===> colorGreen bean initializing...
    ===> colorGreen bean created...
    ===> colorGreen bean initializing...
    
  • 使用@PostConstruct和@Predestroy注解,定义bean:

    public class ColorBlue {
    
        public ColorBlue() {
            System.out.println("===> colorBlue bean created...");
        }
    
        @PostConstruct
        public void init() {
            System.out.println("===> colorBlue bean initializing...");
        }
    
        @PreDestroy
        public void destroy() {
            System.out.println("===> colorBlue bean destroy....");
        }
    }
    

    配置多例模式

    @Bean
    @Scope("prototype")
    public ColorBlue colorBlue() {
        return new ColorBlue();
    }
    

    测试:单例模式跟上面所有方式相同,多例模式下貌似也相同:不管销毁。。。

    @Test
        public void testBeanPostPre() {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationContextConfig.class);
            System.out.println("===> Ioc container created...");
    
            ColorBlue bean = applicationContext.getBean(ColorBlue.class);
            ColorBlue bean2 = applicationContext.getBean(ColorBlue.class);
    
            applicationContext.close();
            System.out.println("===> Ioc container closed...");
        }
    
  • 最后一种:BeanPostProcessor接口,我们看看接口的定义:

    public interface BeanPostProcessor {
    
    	@Nullable
    	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    		return bean;
    	}
    
    	@Nullable
    	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    		return bean;
    	}
    
    }
    

    从两个方法名可以看出,postProcessBeforeInitialization在初始化之前调用,postProcessAfterInitialization在初始化之后调用。大家可以去自行测试一下,这里不再赘述。

### Spring Bean 生命周期详解 Spring 是一个轻量级的 Java 开发框架,其核心功能之一是对 Bean 的管理和控制。Bean生命周期是指从创建到销毁的过程,在这个过程中,Spring 容器会对 Bean 进行一系列的操作和管理。 #### 单例模式下的 Bean 生命周期Spring 中,默认情况下,`singleton` 模式的 Bean 只会在容器启动时被实例化一次,并在整个应用运行期间保持唯一性[^1]。以下是 `singleton` 模式下 Bean 的典型生命周期: 1. **注册 BeanDefinition** 当 Spring 应用上下文启动时,它会解析所有的配置元数据(XML 文件、Java 注解或 Groovy 配置),并将这些信息转换为内部表示形式——`BeanDefinition` 对象[^3]。 2. **合并 BeanDefinition** 如果存在父类定义,则子类的 `BeanDefinition` 将与其父类的定义进行合并,形成最终的 Bean 定义。 3. **实例化前准备** 在实际实例化之前,Spring 会触发一些前置操作,例如通过 `InstantiationAwareBeanPostProcessor` 接口允许开发者自定义实例化的逻辑。 4. **实例化 Bean** Spring 容器根据指定的方式(构造函数或其他方式)来创建 Bean 实例。 5. **属性注入** 创建完成后,Spring 容器会根据配置文件或注解中的定义,将相应的属性值和依赖对象注入到该 Bean 实例中[^4]。 6. **Bean 后处理器处理** 在属性注入之后,Spring 提供了两种类型的后处理器接口: - `BeanPostProcessor`: 允许开发人员在初始化前后对 Bean 进行额外的定制。 - `InstantiationAwareBeanPostProcessor`: 能够更早介入 Bean生命周期,甚至可以在实例化阶段修改行为。 7. **执行 Aware 方法** 如果某个 Bean 实现了一些特定的 `Aware` 接口(如 `ApplicationContextAware`, `BeanNameAware` 等),那么 Spring 容器将会自动调用相应的方法并传入对应的资源。 8. **初始化前回调** 如果 Bean 实现了 `InitializingBean` 接口或者有 `<init-method>` 或者 `@PostConstruct` 标记的方法,Spring 容器将在初始化之前调用它们。 9. **初始化完成** 所有的初始化工作结束后,如果还实现了其他扩展点(如 AOP 动态代理生成等),也会在此阶段完成。 10. **销毁** 对于单例 Bean 来说,当 Spring 容器关闭时才会触发销毁过程;而对于原型作用域 (`prototype`) 下的 Bean,一旦脱离容器范围就不再受控,因此也不会主动销毁。 #### 原型模式下的 Bean 生命周期 与 `singleton` 不同的是,每次请求都会重新创建一个新的 Prototype Bean 实例给客户端使用,而不会对其进行缓存保存。这意味着它的整个生命期完全由外部环境决定而不是 Spring 自己负责跟踪维护。 ```java // 示例代码展示如何定义一个简单的 Bean 并设置其名称 @Configuration public class AppConfig { @Bean(name="myPrototypeBean", initMethod = "initialize", destroyMethod = "cleanup") @Scope("prototype") // 设置为原型作用域 public MyPrototypeBean myPrototypeBean(){ return new MyPrototypeBean(); } } class MyPrototypeBean implements InitializingBean, DisposableBean{ private String message; public void setMessage(String msg){ this.message=msg; } @Override public void afterPropertiesSet() throws Exception { System.out.println("Initializing Bean..."); } @Override public void destroy() throws Exception { System.out.println("Destroying Bean..."); } } ``` 上述例子展示了如何利用 XML 和注解混合的方式来声明一个具有复杂生命周期需求的对象。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值