Spring Bean 的生命周期

文章详细阐述了SpringBean的生命周期,包括实例化、属性赋值、初始化和销毁四个阶段。介绍了不同作用域的bean,如Singleton和Prototype。还涉及了Aware接口,如BeanNameAware和ApplicationContextAware,以及BeanPostProcessor接口在bean创建过程中的作用。通过具体代码示例展示了如何实现和使用这些接口。
摘要由CSDN通过智能技术生成

Spring Bean 的生命周期

一、bean的生命周期

  • 实例化 Instantiation
  • 属性赋值 Populate
  • 初始化 Initialization
  • 销毁 Destruction

实例化 -> 属性赋值 -> 初始化 -> 销毁


1.如果是单例 bean ,随着容器的创建而创建即实例化,多例bean是获取的时候实例化

2.属性注入

3.后处理器前置过程 即在初始化方法之前执行的 方法 postProcessBeforeInitialization

4.初始化方法

5.后处理器后置过程 即在初始化方法之后执行的 方法 postProcessAfterInitialization aop动态代理就在这一步

6.得到最终的 bean

7.销毁

image-20230507221227565

image-20230507221308047

二、bean自身的方法

构造函数、getter/setter 以及 init-method 和 destory-method 所指定的方法等,也就对应着上文说的实例化 -> 属性赋值 -> 初始化 -> 销毁四个阶段。

image-20230507221445455

bean 的作用域:

  • Singleton - 每个 Spring IoC 容器仅有一个单实例。
  • Prototype - 每次请求都会产生一个新的实例。
  • Request - 每一次 HTTP 请求都会产生一个新的实例,并且该 bean 仅在当前 HTTP 请求内有效。
  • Session - 每一次 HTTP 请求都会产生一个新的 bean,同时该 bean 仅在当前 HTTP session 内有效。
  • Global-session - 类似于标准的 HTTP Session 作用域,不过它仅仅在基于 portlet 的 web 应用中才有意义。Portlet 规范定义了全局 Session 的概念,它被所有构成某个 portlet web 应用的各种不同的 portlet 所共享。在 global session 作用域中定义的 bean 被限定于全局 portlet Session 的生命周期范围内。如果你在 web 中使用 global session 作用域来标识 bean,那么 web 会自动当成 session 类型来使用。

仅当用户使用支持 Web 的 ApplicationContext 时,最后三个才可用。

三、Aware接口

可以理解为 Bean 类直接实现接口的方法,比如 BeanNameAwareBeanFactoryAwareApplicationContextAwareInitializingBeanDisposableBean 等方法,例如,实现了BeanNameAware接口,重写setBeanName()方法,可以获得当前的bean的名字。

image-20230507211231775

1,实例化bean对象,以及设置bean属性;

2,如果通过Aware接口声明了依赖关系,则会注入Bean对容器基础设施层面的依赖,Aware接口是为了感知到自身的一些属性。容器管理的Bean一般不需要知道容器的状态和直接使用容器。但是在某些情况下是需要在Bean中对IOC容器进行操作的。这时候需要在bean中设置对容器的感知。SpringIOC容器也提供了该功能,它是通过特定的Aware接口来完成的。 图中所示:

  • BeanNameAware接口,可以知道自己在容器中的名字。
  • BeanFactoryAware接口,有一个方法 setBeanFactory(BeanFactory beanFactory),用来获取当前环境中的 BeanFactory
  • ApplicationContextAware接口,有一个方法 setApplicationContext(ApplicationContext applicationContext),用来获取当前环境中的 ApplicationContext
  • 所有的 Aware 方法都是在初始化阶段之前调用的

3,紧接着会调用BeanPostProcess的前置初始化方法postProcessBeforeInitialization,主要作用是在Spring完成实例化之后,初始化之前,对Spring容器实例化的Bean添加自定义的处理逻辑。有点类似于AOP。

4,如果实现了BeanFactoryPostProcessor接口的afterPropertiesSet方法,做一些属性被设定后的自定义的事情。

5,调用Bean自身定义的init方法,去做一些初始化相关的工作。

6,调用BeanPostProcess的后置初始化方法,postProcessAfterInitialization去做一些bean初始化之后的自定义工作。

7,完成以上创建之后就可以在应用里使用这个Bean了。

image-20230514221422476

四、BeanPostProcessor 一系列接口

BeanPostProcessor 一系列接口:

  • InstantiationAwareBeanPostProcessor

    • 是 BeanPostProcessor 的子接口,常用的有如下三个方法:

      postProcessBeforeInstantiation(Class beanClass, String beanName):在bean实例化之前调用,返回值:如果返回的不为null,那么后续的Bean的创建流程【实例化、初始化afterProperties】都不会执行,而是直接使用返回的快捷Bean
      postProcessProperties(PropertyValues pvs, Object bean, String beanName):在bean实例化之后、设置属性前调用,返回值:如果返回null,那么将不会进行后续的属性填充,比如依赖注入等,如果返回的pvs额外的添加了属性,那么后续会填充到该类对应的属性中。
      postProcessAfterInstantiation(Class beanClass, String beanName):在bean实例化之后调用,返回值:如果有指定的bean的时候返回false,那么后续的属性填充和属性依赖注入populateBean将不会执行,同时后续的postProcessPropertyValues将不会执行,但是初始化和BeanPostProcessor的仍然会执行。

  • BeanPostProcessor

    • 该接口有两个方法:

      postProcessBeforeInitialization(Object bean, String beanName):在初始化之前调用此方法
      postProcessAfterInitialization(Object bean, String beanName):在初始化之后调用此方法

    image-20230508104421773

    image-20230514221051830

    image-20230514221120944

五、代码

image-20230508105024466

UserBean

package com.qf.test;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @author HHy
 * @date 2023/5/1
 * @description UserBean
 */
@Component
public class UserBean implements BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean {

    // id
    private Integer id;
    // 名字
    private String name;

    // 构造函数
    public UserBean(Integer id, String name) {
        this.id = id;
        this.name = name;
        System.out.println("构造函数");
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
        System.out.println("属性注入id");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("属性注入name");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println(name);
        System.out.println("调用BeanNameAware.setBeanName()方法");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        UserBean user = applicationContext.getBean("user", UserBean.class);
        System.out.println(user);
        System.out.println("调用setApplicationContext方法");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("调用 InitializingBean.afterPropertiesSet() 方法");
    }

    public void myInit() {
        System.out.println("init()");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("调用DisposableBean.destroy()");
    }

    public void myDestroy() {
        System.out.println("myDestroy()");
    }

    @Override
    public String toString() {
        return "UserBean{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

MyInstantiationAwareBeanPostProcessor

package com.qf.test;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * @author HHy
 * @date 2023/5/7
 * @desc MyInstantiationAwareBeanPostProcessor
 */
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if ("user".equals(beanName)) {
            System.out.println("调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法");
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if ("user".equals(beanName)) {
            UserBean userBean = (UserBean) bean;
            System.out.println("调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法");
            System.out.println(userBean);
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if ("user".equals(beanName)) {
            System.out.println("调用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法");
        }
        return null;
    }
}

MyBeanPostProcessor

package com.qf.test;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * @author HHy
 * @date 2023/5/7
 * @desc MyBeanPostProcessor
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("user".equals(beanName)) {
            System.out.println("调用 BeanPostProcessor.postProcessBeforeInitialization() 方法");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("user".equals(beanName)) {
            System.out.println("调用 BeanPostProcessor.postProcessAfterInitialization() 方法");
        }
        return bean;
    }
}

bean.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.qf.test.UserBean" init-method="myInit" destroy-method="myDestroy">
        <!-- 构造函数注入 -->
        <constructor-arg name="id" value="1" /> <!-- 除标签名称有变化,其他均和Set注入一致 -->
        <constructor-arg name="name" value="zs" />

        <!-- setter方法注入 -->
        <property name="id" value="2"/>
        <property name="name" value="ls"/>
    </bean>

    <bean id="myBeanPostProcessor" class="com.qf.test.MyBeanPostProcessor"/>
</beans>

Test

package com.qf.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author HHy
 * @date 2023/5/1
 * @description SpringTest
 */
public class SpringTest {

    @Test
    public void Test() {
        AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
        UserBean user = applicationContext.getBean("user", UserBean.class);
        applicationContext.close();
    }
}

ription SpringTest
*/
public class SpringTest {

@Test
public void Test() {
    AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
    UserBean user = applicationContext.getBean("user", UserBean.class);
    applicationContext.close();
}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值