当前位置:   article > 正文

SpringFramework核心 - Bean的生命周期_spring framework的bean生命周期是怎样的

spring framework的bean生命周期是怎样的

面试官:请你描述下 Spring Bean 的生命周期?

1. 概述

网上大部分把Bean生命周期概括为 4 个阶段

  • 实例化(Instantiation):第 1 步,实例化一个 bean 对象
  • 属性赋值(Populate):第 2 步,为 bean 设置相关属性和依赖;
  • 初始化(Initialization):第 3~7 步,步骤较多,其中第 5、6 步为初始化操作,第 3、4 步为在初始化前执行,第 7 步在初始化后执行,该阶段结束,才能被用户使用;
  • 销毁(Destruction):第 8~10步,第8步不是真正意义上的销毁(还没使用呢),而是先在使用前注册了销毁的相关调用接口,为了后面第9、10步真正销毁 bean 时再执行相应的方法
    在这里插入图片描述
    然而如果把Spring Bean的完整生命周期看作从创建Spring容器开始,直到最终Spring容器销毁Bean,还涉及到一些其他扩展点钩子方法的使用

在这里插入图片描述

2. 相关钩子方法和bean生命周期源码分析

Spring有很强的扩展性,主要体现在它为外界提供了许多钩子方法, 比如AwareBeanPostProcessorInitializingBeaninit-method 等都是 Spring 提供的扩展点

2.1 BeanFactoryPostProcessor接口

public interface BeanFactoryPostProcessor {

	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
 
}
  • 1
  • 2
  • 3
  • 4
  • 5

Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以根据需要进行修改,例如可以把beanscopesingleton改为prototype,也可以把property的值给修改掉;它是在spring容器加载了bean的定义文件之后,在bean实例化之前执行的;

Spring允许可以同时配置多个BeanFactoryPostProcessor,并通过设置order属性来控制各个BeanFactoryPostProcessor的执行次序,具体看下面的例子
User

public class User{
    private String name;
    private int age;

    public User() {
        System.out.println("实例化");

    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        System.out.println("初始化 注入age属性");
        this.age = age;
    }

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

  • 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

UserBeanFactoryPostProcessor

public class UserBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    /**
     *
     * @param beanFactory 从工厂中可以获取到相关bean的定义信息
     * @throws BeansException
     */
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("调用UserBeanFactoryPostProcessor的postProcessBeanFactory");
        BeanDefinition user = beanFactory.getBeanDefinition("user");
        //value
        MutablePropertyValues propertyValues = user.getPropertyValues();
        System.out.println("user.age:"+propertyValues.get("age"));
        System.out.println("将年龄更改为22");
        propertyValues.addPropertyValue("age",22);
        System.out.println("UserBeanFactoryPostProcessor的postProcessBeanFactory调用结束");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

applicationContext.xml

<bean id="user" class="com.minifull.pojo.User" scope="singleton">
    <property name="name" value="minifull"></property>
    <property name="age" value="21"></property>
</bean>
<bean id="userBeanFactoryPostProcessor" class="com.minifull.postprocessorpag.UserBeanFactoryPostProcessor"></bean>
  • 1
  • 2
  • 3
  • 4
  • 5
@Test
public void beanFactoryPostProcessortest(){
    ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:applicationContext.xml");
    User user = (User)applicationContext.getBean("user");
    System.out.println(user);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述

2.2 InstantationAwareBeanPostProcessor接口

Spring源码解析(十一)Spring扩展接口InstantiationAwareBeanPostProcessor解析

InstantiationAwareBeanPostProcessor接口继承BeanPostProcessor接口,它内部提供了3个方法,再加上BeanPostProcessor接口内部的2个方法,所以实现这个接口需要实现5个方法。InstantiationAwareBeanPostProcessor接口的主要作用在于目标对象的实例化过程中需要处理的事情,包括实例化对象的前后过程以及实例的属性设置

在这里插入图片描述

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
	//在对象实例化之前调用,直接返回一个对象(如代理对象)来代替通过内置的实例化流程创建对象
	@Nullable
	default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		return null;
	}
	//在对象实例化完成后,执行populateBean之前,判断是否继续进行对属性赋值的流程
	default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
		return true;
	}

	//在Spring处理完默认的成员属性,应用到指定的bean之前进回调,可以用来检查和修改属性
	@Nullable
	default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
			throws BeansException {

		return null;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

从源码分析一下,InstantiationAwareBeanPostProcessor继承了BeanPostProcessor接口,所以他有BeanPostProcessor的特性;
在容器初始化的refresh方法中首先实例化 BeanPostProcessors类型的bean,然后才会实例化剩余 单例并且非懒加载的bean

@Override
	public void refresh() throws BeansException, IllegalStateException {
	// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);
					// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

单例bean的实例化最终是发生在doCreateBean方法中的,而在执行doCreateBean之前有resolveBeforeInstantiation方法

//AbstractAutowireCapableBeanFactory
@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
	// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
	//省略....
	Object beanInstance = doCreateBean(beanName, mbdToUse, args);
	return beanInstance;

	}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

resolveBeforeInstantiation中判断执行InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
	Object bean = null;
	//如果beforeInstantiationResolved还没有设置或者是false(说明还没有需要在实例化前执行的操作)
	if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
		// 判断是否有注册过InstantiationAwareBeanPostProcessor类型的bean
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			Class<?> targetType = determineTargetType(beanName, mbd);
			if (targetType != null) {
				//执行
				bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
				if (bean != null) {
					bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
				}
			}
		}
		mbd.beforeInstantiationResolved = (bean != null);
	}
	return bean;
}
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof InstantiationAwareBeanPostProcessor) {
			InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
			Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
			//只要有一个result不为null;后面的所有 后置处理器的方法就不执行了,直接返回(所以执行顺序很重要)
			if (result != null) {
				return result;
			}
		}
	}
	return null;
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		result = beanProcessor.postProcessAfterInitialization(result, beanName);
		//如果返回null;后面的所有 后置处理器的方法就不执行,直接返回(所以执行顺序很重要)
		if (result == null) {
			return result;
		}
	}
	return result;
}
  • 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

从上面代码可以看出:

1. 如果postProcessBeforeInstantiation方法返回了Object是null;那么就直接返回,调用doCreateBean方法();

2. 如果postProcessBeforeInstantiation返回不为null;说明修改了bean对象;然后这个时候就立马执行postProcessAfterInitialization方法(注意这个是初始化之后的方法,也就是通过这个方法实例化了之后,直接执行初始化之后的方法;中间的实例化之后 和 初始化之前都不执行);

3. 在调用postProcessAfterInitialization方法时候如果返回null;那么就直接返回,调用doCreateBean方法();(初始化之后的方法返回了null,那就需要调用doCreateBean生成对象了)

4. 在调用postProcessAfterInitialization时返回不为null;那这个bean就直接返回给ioc容器了 初始化之后的操作 是这里面最后一个方法了;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

可以看到我们在postProcessBeforeInstantiationpostProcessAfterInitialization返回了对象,就不再执行Spring内部接下来的doCreateBean方法了,而是直接返回我们定义的对象,通过这一点我们可以生成一个代理类

2.3 Aware 接口

spring源码:Aware接口
Spring 检测到 bean 实现了 Aware 接口,则会为其注入相应的依赖。所以通过让bean 实现 Aware 接口,则能在 bean 中获得相应的 Spring 容器资源。
Spring 中提供的 Aware 接口有:

BeanNameAware:注入当前 bean 对应 beanName
BeanClassLoaderAware:注入加载当前 beanClassLoader
BeanFactoryAware:注入 当前BeanFactory容器 的引用
ApplicationContextAware

如我们想得到当前的BeanFactory,我们可以让我们的实现类继承BeanFactoryAware接口,然后通过接口注入的方式得到当前容器中的BeanFactory

public class User implements BeanFactoryAware {
    private BeanFactory beanFactory;
    private String name;
    private int age;
	//get set...
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactoryAware: 为UserBean注入beanFactory属性");
        this.beanFactory = beanFactory;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在这里插入图片描述

2.4 BeanPostProcessor接口

BeanPostProcessor,可以在spring容器实例化bean之后,在执行bean的初始化方法前后,添加一些自己的处理逻辑。这里说的初始化方法,指的是下面两种:
bean实现了InitializingBean接口,对应的方法为afterPropertiesSet

② 在bean定义的时候,通过init-method设置的方法

public interface BeanPostProcessor {

	// 初始化前置处理
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	// 初始化后置处理
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

BeanPostProcessor的常用场景有:

  • 对于标记接口的实现类,进行自定义处理
  • 为当前对象提供代理实现。例如 Spring AOP 功能,生成对象的代理类,然后返回

使用如下:


/**
 * bean的后置处理器
 * 分别在bean的初始化前后对bean对象提供自己的实例化逻辑
 * postProcessAfterInitialization:初始化之后对bean进行增强处理
 * postProcessBeforeInitialization:初始化之前对bean进行增强处理
 *
 */
public class MyBeanPostProcessor implements BeanPostProcessor {

    //对初始化之后的Bean进行处理
    //参数:bean:即将初始化的bean
    //参数:beanname:bean的名称
    //返回值:返回给用户的那个bean,可以修改bean也可以返回一个新的bean

    public Object postProcessAfterInitialization(Object bean, String beanname) throws BeansException {
        User user = null;
        System.out.println("调用BeanPostProcessor的postProcessAfterInitialization方法:对初始化之后的Bean进行处理,将user的name改为Jack");
        if("name".equals(beanname) || bean instanceof User) {
            user = (User) bean;
            user.setName("Jack");
        }
        return user;
    }

    //对初始化之前的Bean进行处理
    //参数:bean:即将初始化的bean
    //参数:beanname:bean的名称
    //返回值:返回给用户的那个bean,可以修改bean也可以返回一个新的bean

    public Object postProcessBeforeInitialization(Object bean, String beanname) throws BeansException {
        System.out.println("调用BeanPostProcessor的postProcessBeforeInitialization方法: 对初始化之前的Bean进行处理,此时我的名字"+bean);
        return 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
<bean id="user" class="com.minifull.pojo.User" scope="singleton">
    <property name="name" value="minifull"></property>
    <property name="age" value="21"></property>
</bean>
<bean id="userBeanFactoryPostProcessor" class="com.minifull.postprocessorpag.UserBeanFactoryPostProcessor"></bean>
<!-- 配置bean的后置处理器,不需要id,IoC容器自动识别是一个BeanPostProcessor -->
<bean class="com.minifull.postprocessorpag.MyBeanPostProcessor"></bean>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

2.5 InitializingBeanDisposableBean接口

InitializingBeanSpringbean 初始化提供的扩展点,可以添加自定义的初始化方法或者做一些资源初始化操作,当BeanFactory 设置完所有的Bean属性之后才会调用afterPropertiesSet方法

InitializingBean接口 的定义如下

public interface InitializingBean {
	void afterPropertiesSet() throws Exception;
}
  • 1
  • 2
  • 3

DisposableBean接口只有一个方法destroy,作用是:当一个单例Bean实现DisposableBeandestroy可以添加自定义的一些销毁方法或者资源释放操作

2.6 init-method

指定 init-method 方法,指定初始化方法:

public class User implements BeanFactoryAware {
    private BeanFactory beanFactory;
    private String name;
    private int age;

    public User() {
        System.out.println("实例化");

    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        System.out.println("初始化 注入age属性");
        this.age = age;
    }
    //Bean的初始化方法
    public void initUser() {
        System.out.println("Bean:init Method");
    }

    //Bean的销毁方法
    public void destroyUser() {
        System.out.println("Bean:destroy Method");
    }

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

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactoryAware: 为UserBean注入beanFactory属性");
        this.beanFactory = beanFactory;
    }
}
  • 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
<bean id="user" class="com.minifull.pojo.User" scope="singleton"  init-method="initUser" destroy-method="destroyUser">
    <property name="name" value="minifull"></property>
    <property name="age" value="21"></property>
</bean>
<bean id="userBeanFactoryPostProcessor" class="com.minifull.postprocessorpag.UserBeanFactoryPostProcessor"></bean>
<!-- 配置bean的后置处理器,不需要id,IoC容器自动识别是一个BeanPostProcessor -->
<bean class="com.minifull.postprocessorpag.MyBeanPostProcessor"></bean>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
@Test
public void test1(){
    FileSystemXmlApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:applicationContext.xml");
    User user = (User)applicationContext.getBean("user");
    System.out.println(user);
    applicationContext.close();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述

针对上面的初始化,销毁等操作在 doCreateBean() 方法中能看到依次执行了这 4 个阶段:

// AbstractAutowireCapableBeanFactory.java
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
    throws BeanCreationException {

    // 1. 实例化
    BeanWrapper instanceWrapper = null;
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    
    Object exposedObject = bean;
    try {
        // 2. 属性赋值
        populateBean(beanName, mbd, instanceWrapper);
        // 3. 初始化
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }

    // 4. 销毁-注册回调接口
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }

    return exposedObject;
}
  • 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

关注一下initializeBean() 初始化的过程,这部分比较复杂

// AbstractAutowireCapableBeanFactory.java
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    // 3. 检查 Aware 相关接口并设置相关依赖
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        invokeAwareMethods(beanName, bean);
    }

    // 4. BeanPostProcessor 前置处理
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    // 5. 若实现 InitializingBean 接口,调用 afterPropertiesSet() 方法
    // 6. 若配置自定义的 init-method方法,则执行
    try {
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
    }
    // 7. BeanPostProceesor 后置处理
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}
  • 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

invokInitMethods() 方法中会检查 InitializingBean 接口和 init-method 方法,销毁的过程也与其类似:

// DisposableBeanAdapter.java
public void destroy() {
    // 9. 若实现 DisposableBean 接口,则执行 destory()方法
    if (this.invokeDisposableBean) {
        try {
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ((DisposableBean) this.bean).destroy();
                    return null;
                }, this.acc);
            }
            else {
                ((DisposableBean) this.bean).destroy();
            }
        }
    }
    
	// 10. 若配置自定义的 detory-method 方法,则执行
    if (this.destroyMethod != null) {
        invokeCustomDestroyMethod(this.destroyMethod);
    }
    else if (this.destroyMethodName != null) {
        Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
        if (methodToInvoke != null) {
            invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
        }
    }
}
  • 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
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/66354
推荐阅读
相关标签
  

闽ICP备14008679号