1. Spring中Bean的生命周期

ApplicationContext Bean生命周期流程

spring入门_初始化
ApplicationContext容器中,Bean的生命周期流程如上图所示,流程大致如下:

1.首先容器启动后,会对scope为singleton且非懒加载的bean进行实例化,

2.按照Bean定义信息配置信息,注入所有的属性,

3.如果Bean实现了BeanNameAware接口,会回调该接口的setBeanName()方法,传入该Bean的id,此时该Bean就获得了自己在配置文件中的id,

4.如果Bean实现了BeanFactoryAware接口,会回调该接口的setBeanFactory()方法,传入该Bean的BeanFactory,这样该Bean就获得了自己所在的BeanFactory,

5.如果Bean实现了ApplicationContextAware接口,会回调该接口的setApplicationContext()方法,传入该Bean的ApplicationContext,这样该Bean就获得了自己所在的ApplicationContext,

6.如果有Bean实现了BeanPostProcessor接口,则会回调该接口的postProcessBeforeInitialzation()方法,

7.如果Bean实现了InitializingBean接口,则会回调该接口的afterPropertiesSet()方法,

8.如果Bean配置了init-method方法,则会执行init-method配置的方法,

9.如果有Bean实现了BeanPostProcessor接口,则会回调该接口的postProcessAfterInitialization()方法,

10.经过流程9之后,就可以正式使用该Bean了,对于scope为singleton的Bean,Spring的ioc容器中会缓存一份该bean的实例,而对于scope为prototype的Bean,每次被调用都会new一个新的对象,期生命周期就交给调用方管理了,不再是Spring容器进行管理了

11.容器关闭后,如果Bean实现了DisposableBean接口,则会回调该接口的destroy()方法,

12.如果Bean配置了destroy-method方法,则会执行destroy-method配置的方法,至此,整个Bean的生命周期结束

代码示例:

  1. bean类代码
package com.atguigu.configuration;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * @USER: 
 * @DATE: 2021-07-13
 * @description:测试bean的生命周期
 */
public class BookBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean
, DisposableBean {

    private String id;
    private String name;
    private String author;

    public BookBean(){
        System.out.println("BookBean构造方法被调用");
    }

    //1.set注入 按照Spring上下文对实例化的Bean进行配置,也就是IOC注入
    public void setId(String id) {
        System.out.println("1.setId被调用");
        this.id = id;
    }

    public void setName(String name) {
        System.out.println("1.setNames被调用");
        this.name = name;
    }
    public void setAuthor(String author) {
        System.out.println("1.setAuthor被调用");
        this.author = author;
    }

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

    //2.调用BeanNameAware的setBeanName方法 设置bean的名字  此处传递的是Spring配置文件中Bean的ID
    @Override
    public void setBeanName(String s) {
        System.out.println("2.调用BeanNameAware的setBeanName方法");
    }

    //3.调用BeanFactoryAware的setBeanFactory 设置Bean的工厂模式 传递的是Spring工厂本身(可以用这个方法获取到其他Bean)
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("3.调用BeanFactoryAware的setBeanFactory方法");
    }

    //4.调用ApplicationContextAware的setApplicationContext方法 传入Spring上下文
    // 以为ApplicationContext是BeanFactory的子接口,有更多的实现方法
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("4.调用ApplicationContextAware的setApplicationContext方法");
    }
    //6.调用调用InitizingBean的afterPropertiesSet方法
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("6.调用InitizingBean的afterPropertiesSet方法");
    }
    //7.调用初始化方法
    public void myInit(){
        System.out.println("7.调用定制的初始化方法");
    }
    //9.调用DispostbleBean的destroy
    @Override
    public void destroy() throws Exception {
        System.out.println("9.调用DispostbleBean的destroy方法");
    }
    //10.调用定制的销毁方法
    public void myDestroy(){
        System.out.println("9.调用定制的销毁方法");
    }
}

2.后置处理器代码:

package com.atguigu.configuration;

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

/**
 * @USER: 
 * @DATE: 2021-07-13
 * @description:功能描述
 */
public class MyBeanPostProcessor implements BeanPostProcessor {

    //5.调用BeanPostProcessor的postProcessBeforeInitialization方法
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("5.调用BeanPostProcessor的postProcessBeforeInitialization方法");
        return bean;
    }
    //8.调用BeanPostProcessor的postProcessAfterInitialization方法
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("8.调用BeanPostProcessor的postProcessAfterInitialization方法");
        return bean;
    }
}

3.配置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"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                          ">
    <bean id="book1" destroy-method="myDestroy" init-method="myInit" class="com.atguigu.configuration.BookBean">
        <property name="name" value="老人与海"></property>
        <property name="author" value="哈利波特"></property>
        <property name="id" value="101"></property>
    </bean>

    <!--配置自定义的后置处理器 -->
    <bean id="postProcessor" class="com.atguigu.configuration.MyBeanPostProcessor"></bean>

</beans>

4.测试

public class TestBookBean {

    @Test
    public void test(){
        System.out.println("0.容器开始初始化");
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        System.out.println("xml加载完毕");
        BookBean bookBean = context.getBean("book1",BookBean.class);
        System.out.println(bookBean.toString());
        System.out.println("11.关闭容器");
        ((ClassPathXmlApplicationContext)context).close();
    }

}

5.控制台打印

0.容器开始初始化
BookBean构造方法被调用
1.setNames被调用
1.setAuthor被调用
1.setId被调用
2.调用BeanNameAware的setBeanName方法
3.调用BeanFactoryAware的setBeanFactory方法
4.调用ApplicationContextAware的setApplicationContext方法
5.调用BeanPostProcessor的postProcessBeforeInitialization方法
6.调用InitizingBean的afterPropertiesSet方法
7.调用定制的初始化方法myInit
8.调用BeanPostProcessor的postProcessAfterInitialization方法

 xml加载完毕,Bean准备就绪
BookBean{id='101', name='老人与海', author='哈利波特'}
11.关闭容器
9.调用DispostbleBean的destroy方法
9.调用定制的销毁方法

spring入门_生命周期_02

Instance实例例化-》设置属性值-》调⽤用BeanNameAware的setBeanName⽅方法-》调⽤用BeanPostProsessor的预初始化⽅方
法-》调⽤用InitializationBean的afterPropertiesSet()的⽅方法-》调⽤用定制的初始化⽅方法callCustom的init-method-》调⽤用
BeanPostProsessor的后初始化⽅方法-》Bean可以使⽤用了了 -》 容器器关闭-》 调⽤用DisposableBean的destroy⽅方法-》调⽤用定
制的销毁⽅方法CallCustom的destroy-method。

1、Spring对Bean进⾏行行实例例化(相当于程序中的new Xx())
2、Spring将值和Bean的引⽤用注⼊入进Bean对应的属性中
3、如果Bean实现了了BeanNameAware接⼝口,Spring将Bean的ID传递给setBeanName()⽅方法(实现BeanNameAware清主
要是为了了通过Bean的引⽤用来获得Bean的ID,⼀一般业务中是很少有⽤用到Bean的ID的)
4、如果Bean实现了了BeanFactoryAware接⼝口,Spring将调⽤用setBeanDactory(BeanFactory bf)⽅方法并把BeanFactory容器器
实例例作为参数传⼊入。(实现BeanFactoryAware 主要⽬目的是为了了获取Spring容器器,如Bean通过Spring容器器发布事件等)
5、如果Bean实现了了ApplicationContextAwaer接⼝口,Spring容器器将调⽤用setApplicationContext(ApplicationContext ctx)
⽅方法,把y应⽤用上下⽂文作为参数传⼊入.(作⽤用与BeanFactory类似都是为了了获取Spring容器器,不不同的是Spring容器器在调⽤用
setApplicationContext⽅方法时会把它⾃自⼰己作为setApplicationContext 的参数传⼊入,⽽而Spring容器器在调⽤用setBeanDactory
前需要程序员⾃自⼰己指定(注⼊入)setBeanDactory⾥里里的参数BeanFactory )
7、如果Bean实现了了BeanPostProcess接⼝口,Spring将调⽤用它们的postProcessBeforeInitialization(预初始化)⽅方法(作
⽤用是在Bean实例例创建成功后对进⾏行行增强处理理,如对Bean进⾏行行修改,增加某个功能)7.如果Bean实现了了InitializingBean接
⼝口,Spring将调⽤用它们的afterPropertiesSet⽅方法,作⽤用与在配置⽂文件中对Bean使⽤用init-method声明初始化的作⽤用⼀一样,
都是在Bean的全部属性设置成功后执⾏行行的初始化⽅方法。
8、如果Bean实现了了BeanPostProcess接⼝口,Spring将调⽤用它们的postProcessAfterInitialization(后初始化)⽅方法(作
⽤用与7的⼀一样,只不不过7是在Bean初始化前执⾏行行的,⽽而这个是在Bean初始化后执⾏行行的,时机不不同 )
9、经过以上的⼯工作后,Bean将⼀一直驻留留在应⽤用上下⽂文中给应⽤用使⽤用,直到应⽤用上下⽂文被销毁
10、如果Bean实现了了DispostbleBean接⼝口,Spring将调⽤用它的destory⽅方法,作⽤用与在配置⽂文件中对Bean使⽤用destory-
method属性的作⽤用⼀一样,都是在Bean实例例销毁前执⾏行行的⽅方法。

1.1 实例化 也就是我们通常说的new

  • setter 方法
  • 构造函数
  • 静态工厂
  • 实例工厂