• Spring - IoC 容器之 Bean 的生命周期


    概述

    Bean 的生命周期就是 Bean创建 - 初始化 - 销毁 过程

    Spring IoC 容器 管理一个或多个 Bean。这些 Bean 通过我们定义的配置信息进行创建。在容器内部,这些 Bean 定义表示为 BeanDefinition 对象,它包含了以下元数据:

    • package-qualified 类名:通常是被定义 Bean 的实际实现类
    • Bean 行为配置元素,规定了 Bean 在容器中的行为(scope生命周期回调 等)
    • Bean 执行其工作所需要的其他 Bean 的引用。这些引用也称为 依赖
    • 要在新创建的对象中设置的其他配置设置,例如 pool 的大小限制,或者在管理连接池的 Bean 中使用的连接数
    public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    
    	...
    
    	void setBeanClassName(@Nullable String beanClassName);
    
    	@Nullable
    	String getBeanClassName();
    
    
    	void setScope(@Nullable String scope);
    
    	@Nullable
    	String getScope();
    
    	...
    
    	void setDependsOn(@Nullable String... dependsOn);
    
    	@Nullable
    	String[] getDependsOn();
    
    	void setPrimary(boolean primary);
    
    	boolean isPrimary();
    
    	void setFactoryBeanName(@Nullable String factoryBeanName);
    
    	/**
    	 * Return the factory bean name, if any.
    	 */
    	@Nullable
    	String getFactoryBeanName();
    
    	void setFactoryMethodName(@Nullable String factoryMethodName);
    	
    	@Nullable
    	String getFactoryMethodName();
    
    	...
    
    	void setInitMethodName(@Nullable String initMethodName);
    
    	@Nullable
    	String getInitMethodName();
    
    	void setDestroyMethodName(@Nullable String destroyMethodName);
    
    	@Nullable
    	String getDestroyMethodName();
    
    	...
    
    	boolean isSingleton();
    
    	/**
    	 * Return whether this a Prototype, with an independent instance
    	 * returned for each call.
    	 * @since 3.0
    	 * @see #SCOPE_PROTOTYPE
    	 */
    	boolean isPrototype();
    
    	/**
    	 * Return whether this bean is "abstract", that is, not meant to be instantiated.
    	 */
    	boolean isAbstract();
    
    	...
    }
    
    • 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

    实例化(创建) Bean

    通过 构造器 实例化

    当使用构造器实例化 Bean 时,只需要普通类的默认(无参)构造器即可。

    public class Car {
    
        public Car() {
            System.out.println("car constructor...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    @Bean
    public Car car() {
        return new Car();
    }
    
    // 初始化 IoC 容器会输出
    car constructor...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    通过 静态工厂方法 实例化

    public class ClientService {
    
        private static ClientService clientService = new ClientService();
    
        public ClientService() {
            System.out.println("init by constructor...");
        }
    
        public static ClientService createInstance() {
            return clientService;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    
    <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">
    
        <bean id="clientService"
              class="com.keke.bean.ClientService"
              factory-method="createInstance"/>
    beans>
    
    // 初始化 IoC 容器会输出
    init by constructor...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    通过 实例工厂方法 实例化

    与使用 静态工厂方法 进行实例化相比,使用 实例工厂方法 进行的实例化从容器中调用现有 Bean 的非静态方法来创建 Bean。要使用这种方法,需要将 class 属性保留为空,并在 factory-bean 属性中指定包含用于创建对象的实例方法的当前(或父或祖先)容器中的 Bean 名称。使用 factory-method 属性设置工厂方法本身的名称。举例如下:

    // 首先定义一个接口
    public interface ClientService {}
    
    // 定义两个实现类
    public class ClientServiceImpl implements ClientService {}
    
    public class AccountServiceImpl implements ClientService {}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    定义一个类作为 factory bean 并加入到 IoC 容器 中,用于通过实例或静态工厂方法创建对象:

    public class DefaultServiceLocator {
    
        private static ClientService clientService = new ClientServiceImpl();
        private static ClientService accountService = new AccountServiceImpl();
    
        public ClientService createClientServiceInstance() {
            return clientService;
        }
    
        public ClientService createAccountServiceInstance() {
            return accountService;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    
    <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">
    
        <bean id="serviceLocator" class="com.keke.bean.DefaultServiceLocator">
    		// 这里可以进行依赖注入
    	bean>
    
        <bean id="clientService"
              factory-bean="serviceLocator"
              factory-method="createClientServiceInstance"/>
    
        <bean id="accountService"
              factory-bean="serviceLocator"
              factory-method="createAccountServiceInstance"/>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    自定义 Bean 的生命周期(初始化和销毁方法)

    Spring 官方文档 中我们了解到,在 Spring 2.5 开始,我们有三种方式指定 Bean 的生命周期:

    1、@Bean 注解指定初始化和销毁方法

    public class Car {
    
        public void init() {
            System.out.println("car init...");
        }
    
        public void destory() {
            System.out.println("car destory...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    @Bean(initMethod = "init", destroyMethod = "destory")
    public Car car() {
        return new Car();
    }
    
    • 1
    • 2
    • 3
    • 4

    2、InitializingBeanDisposableBean 接口

    @Component
    public class Cat implements InitializingBean, DisposableBean {
    
        @Override
        public void destroy() throws Exception {
            System.out.println("cat destroy...");
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("cat afterPropertiesSet...");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3、@PostConstruct@PreDestory

    @Component
    public class Dog {
    
        @PostConstruct
        public void init() {
            System.out.println("dog init");
        }
    
        @PreDestroy
        public void destroy() {
            System.out.println("dog destroy");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    除了 初始化销毁 回调,由 Spring 管理的对象还可以实现 Lifecycle 接口,以便这些对象可以参与启动和关闭过程,这是由容器自己的生命周期驱动的。

    总结

    以上三种指定 Bean 生命周期的方式作用于同一个 Bean 上是有先后顺序的:

    • 初始化方法

      • @PostConstruct
      • InitializingBean 中的 afterPropertiesSet()
      • @Bean 中指定 init()
    • 销毁方法

      • @PreDestroy
      • DisposableBean 中的 destory()
      • @Bean 中指定 destroy()

    验证代码如下:

    public class Car implements InitializingBean, DisposableBean {
    
        public void init() {
            System.out.println("car init by @Bean");
        }
    
        public void destory() {
            System.out.println("car destroy by @Bean");
        }
    
        @Override
        public void destroy() throws Exception {
            System.out.println("car destroy by DisposableBean");
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("car init by InitializingBean");
        }
    
        @PostConstruct
        public void initi() {
            System.out.println("car init by @PostConstruct");
        }
    
        @PreDestroy
        public void destroyi() {
            System.out.println("car destroy by @PreDestroy");
        }
    }
    
    • 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

    初始化 IoC 容器 后关闭容器,结果输出:

    car init by @PostConstruct
    car init by InitializingBean
    car init by @Bean
    car destroy by @PreDestroy
    car destroy by DisposableBean
    car destroy by @Bean
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    机器学习-k-近邻算法
    通义灵码-ai编码
    神经网络入门
    错误:ModuleNotFoundError: No module named ‘httplib‘
    Eclipse中集成Tomcat
    查找算法【哈希表】 - 简介
    Android sqlcipher 对于加密的Sqlite库在Mac上进行解密的正确姿势
    【GNN】【ICML2019】Position-aware GraphNeural Networks
    数据结构--堆
    网络编程入门
  • 原文地址:https://blog.csdn.net/qiaohao0206/article/details/125876005