• Bean的生命周期及演示



    一、介绍

    概念

    Bean的生命周期是指一个Bean对象从创建到销毁的整个存在过程。


    Bean生命周期组成:

    1.实例化Bean(为Bean分配内存空间)
    2.属性注入 (Bean注入和装配)
    3.Bean的初始化

    • 各种通知:如 BeanNameWare、BeanFactoryAware、ApplicationContextAware 的接口方法。
    • 初始化前置方法
    • 执行初始化方法
      • 注解方式:@PostConstruct
      • xml 方式:init-method 方法
    • 初始化后置方法

    4.使用Bean
    5.销毁Bean

    注:

    通过 @PostConstruct 注解方式初始化,需要在配置文件设置扫描路径;
    通过 xml 方式初始化,需要在配置文件用标签中的 init-method 属性配置对应类的初始化方法名。


    二、实例演示

    spring-config.xml

    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:content="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
        <content:component-scan base-package="com">content:component-scan>
        <bean id="beanLifeComponent" 
        class="com.example.BeanLifeComponent" init-method="init">bean>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注:init-method 属性的值是 bean 对应的初始化方法的名称。如果该属性的值不匹配方法名,则在初始化 bean 时会抛出 NoSuchMethodException 异常。此处 ‘init’ 对应下面 xml 方式初始化方法名。

    com.example.BeanLifeComponent.java

    package com.example;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.BeanFactoryAware;
    import org.springframework.beans.factory.BeanNameAware;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    
    public class BeanLifeComponent implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, BeanPostProcessor {
        /**
         * 执行通知方法
         * @param s
         */
        @Override
        public void setBeanName(String s) {
            System.out.println("执行了BeanNameAware:BeanName = " + s);
        }
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            System.out.println("执行了BeanFactoryAware:BeanFactory = " + beanFactory);
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            System.out.println("执行了ApplicationContextAware:ApplicationContext = " + applicationContext);
        }
    
        /**
         * 执行初始化前置方法
         * @param bean
         * @param beanName
         * @return
         * @throws BeansException
         */
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("执行初始化前置方法");
            return bean;
        }
    
        /**
         * 执行初始化方法
         */
        //xml 方式的初始化方法
        public void init(){
            System.out.println("XML 方式初始化");
        }
    
        //注解 方式初始化
        @PostConstruct
        public void postConstruct() {
            System.out.println("注解 方式初始化");
        }
    
        /**
         * 执行初始化后置方法
         * @param bean
         * @param beanName
         * @return
         * @throws BeansException
         */
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("执行初始化后置方法");
            return bean;
        }
    
        /**
         * 使用Bean
         */
        public void sayHi(){
            System.out.println("使用Bean");
        }
    
        /**
         * 销毁Bean
         */
        @PreDestroy
        public void preDestroy() {
            System.out.println("销毁Bean");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88

    BeanLifeTest.java

    import com.example.BeanLifeComponent;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class BeanLifeTest {
        public static void main(String[] args) {
            //得到 Spring 容器,通过配置文件让Spring容器自动完成对象的实例化和属性注入。
            // 这里使用 ClassPathXmlApplicationContext 而不是 ApplicationContext,因为这个类没有destroy()或者close()方法。
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
    
            //获取Bean
            BeanLifeComponent bean = context.getBean("beanLifeComponent", BeanLifeComponent.class);
    
            //使用Bean
            bean.sayHi();
    
            //销毁Bean。下面两种方法等效
            //context.destroy();
            context.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    运行 BeanLifeTest.java 打印结果:
    在这里插入图片描述
    从打印结果我们可以发现:
    1.使用注解方式初始化Bean比使用xml的优先级高。
    2.为什么没有执行初始化前置和后置方法?
    答:因为Bean的作用域默认是单例,Spring会自动调用初始化前置方法和后置方法,我们不能显示调用。要想显示调用,把Bean的作用域改为 prototype 即多例模式。可以在XML配置文件中使用元素的scope属性修改,也可在Bean定义中使用@Scope注解修改。


    修改后
    在这里插入图片描述
    再次运行打印结果:
    在这里插入图片描述
    可以发现:
    1.方法执行了两次。一个是在应用上下文启动时初始化的实例,另一个是在执行 getBean 方法时返回一个新的实例并初始化。
    2.为什么没有执行销毁方法?
    答:是因为Spring设计,多例模式的 Bean 由于会创建多个实例,因此容器不会自动跟踪和销毁这些实例,而是直接停掉了整个线程。

  • 相关阅读:
    【Django】Django REST Framework接口实现详解:从APIView到ModelViewSet
    ElementUI搭建使用过程
    数据结构与算法_排序算法_插入排序和希尔排序
    SQL编程 Task05.SQL高级处理
    数学计算式转为表达式树
    【必知必会的MySQL知识】③DML语言
    Go 将在下个版本支持新型排序算法:pdqsort
    Java之转换流的详细解析
    xunhuan Jacobi method SVD
    MongoDB 原子操作:确保数据一致性和完整性的关键
  • 原文地址:https://blog.csdn.net/weixin_52938032/article/details/130598718