溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring Bean有哪些生命周期

發(fā)布時間:2021-08-05 16:47:53 來源:億速云 閱讀:166 作者:Leah 欄目:編程語言

這篇文章給大家介紹Spring Bean有哪些生命周期,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

生命周期解讀:

1. 注冊階段
2. 實例化階段
3. 初始化階段
4. 銷毀階段

Spring Bean有哪些生命周期

注冊階段

注冊階段主要任務是通過各種BeanDefinitionReader讀取掃描各種配置來源信息(xml文件、注解等),并轉換為BeanDefinition的過程。

BeanDefinition可以理解為類的定義,描述一個類的基本情況,比較像我們注冊某些網(wǎng)站時的基本信息,比如需要填寫姓名、住址、出生日期等。

最終會將我們掃描到的類整體注冊到一個DefaultListableBeanFactory的Map容器中,便于我們之后獲取使用。

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
	//存儲注冊信息的BeanDefinition
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
	//beanDefinitionMap的數(shù)據(jù)結構是ConcurrentHashMap,因此不能保證順序,為了記錄注冊的順序,這里使用了ArrayList類型beanDefinitionNames用來記錄注冊順序
	private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
	
	//省略部分代碼.......
	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
		//省略判斷代碼.......
		// Still in startup registration phase
		this.beanDefinitionMap.put(beanName, beanDefinition);
		this.beanDefinitionNames.add(beanName);
	}
}
實例化階段

在實例化階段,Spring主要將BeanDefinition轉換為實例Bean,并放在包裝類BeanWrapper中。

無論是否設置Bean的懶加載方式,最后都會通過AbstractBeanFactory.getBean()方法進行實例化,并進入到AbstractAutowireCapableBeanFactory.createBean()方法。

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
	//省略部分代碼......
	@Nullable
	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			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;
	}
	//省略部分代碼......
}

在實例化階段AbstractAutowireCapableBeanFactory.createBeanInstance()完成Bean的創(chuàng)建,并放到BeanWrapper中。

初始化階段

初始化階段主要是在返回Bean之前做一些處理,主要由AbstractAutowireCapableBeanFactory.initializeBean()方法實現(xiàn)。

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
	//省略部分代碼......
	//真正創(chuàng)建Bean的方法
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		//省略部分代碼......
		// Initialize the bean instance.
		//Bean對象的初始化,依賴注入在此觸發(fā)
		//這個exposedObject在初始化完成之后返回作為依賴注入完成后的Bean
		Object exposedObject = bean;
		try {
			//將Bean實例對象封裝,并且Bean定義中配置的屬性值賦值給實例對象
			populateBean(beanName, mbd, instanceWrapper);
			//初始化Bean對象
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}
		//省略部分代碼......
		return exposedObject;
	}
	
	//初始容器創(chuàng)建的Bean實例對象,為其添加BeanPostProcessor后置處理器
	protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		//JDK的安全機制驗證權限
		if (System.getSecurityManager() != null) {
			//實現(xiàn)PrivilegedAction接口的匿名內(nèi)部類
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			//為Bean實例對象包裝相關屬性,如名稱,類加載器,所屬容器等信息
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		//對BeanPostProcessor后置處理器的postProcessBeforeInitialization
		//回調(diào)方法的調(diào)用,為Bean實例初始化前做一些處理
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		//調(diào)用Bean實例對象初始化的方法,這個初始化方法是在Spring Bean定義配置
		//文件中通過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);
		}
		//對BeanPostProcessor后置處理器的postProcessAfterInitialization
		//回調(diào)方法的調(diào)用,為Bean實例初始化之后做一些處理
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}
	//省略部分代碼......
}
銷毀階段

一般是在ApplicationContext關閉的時候調(diào)用,也就是AbstractApplicationContext.close() 方法。

在注冊的時候Spring通過適配器模式包裝了一個類DisposableBeanAdapter,在銷毀階段的時候會獲得這個類,進而調(diào)用到DisposableBeanAdapter.destroy()方法:

class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
	//省略部分代碼......
	@Override
	public void destroy() {
		if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
			for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
				processor.postProcessBeforeDestruction(this.bean, this.beanName);
			}
		}

		if (this.invokeDisposableBean) {
			if (logger.isDebugEnabled()) {
				logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
			}
			try {
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
						((DisposableBean) bean).destroy();
						return null;
					}, acc);
				}
				else {
					((DisposableBean) bean).destroy();
				}
			}
			catch (Throwable ex) {
				String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
				if (logger.isDebugEnabled()) {
					logger.warn(msg, ex);
				}
				else {
					logger.warn(msg + ": " + ex);
				}
			}
		}

		if (this.destroyMethod != null) {
			invokeCustomDestroyMethod(this.destroyMethod);
		}
		else if (this.destroyMethodName != null) {
			Method methodToCall = determineDestroyMethod(this.destroyMethodName);
			if (methodToCall != null) {
				invokeCustomDestroyMethod(methodToCall);
			}
		}
	}
	//省略部分代碼......
}

銷毀階段主要包括三個銷毀途徑,按照執(zhí)行順序:

  1. @PreDestroy注解,主要通過DestructionAwareBeanPostProcessor實現(xiàn)

  2. 實現(xiàn)DisposableBean接口,主要通過DisposableBean.destroy()實現(xiàn)

  3. 自定義銷毀方 DisposableBeanAdapter.invokeCustomDestroyMethod()實現(xiàn)

實例測試

下邊通過一個簡單實例來做一個簡單測試。

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

/**
 * @Author: maomao
 * @Date: 2021-04-18 20:50
 */
public class User implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean, ApplicationContextAware, ApplicationEventPublisherAware {

    private String name;

    private int age;

    private BeanFactory beanFactory;

    private String beanName;

    public User(){
        System.out.println("User【構造方法】默認構造方法!");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("User【注入屬性】name " + name);
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
        System.out.println("User【注入屬性】age " + age);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("【BeanFactoryAware接口】調(diào)用setBeanFactory " + beanFactory);
        this.beanFactory = beanFactory;
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("【BeanNameAware接口】setBeanName " + name);
        this.beanName = name;
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("【DisposableBean接口】destroy");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("【InitializingBean接口】InitializingBean");
    }

    public void initMethod(){
        System.out.println("【initMethod方法】initMethod");
    }

    public void destroyMethod(){
        System.out.println("【destroyMethod方法】destroyMethod");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("【ApplicationContextAware接口】setApplicationContext " + applicationContext);
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        System.out.println("【ApplicationEventPublisherAware接口】setApplicationEventPublisher " + applicationEventPublisher);
    }
}

application.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="beanPostProcessor" class="com.freecloud.spring.lifecycle.MyBeanPostProcessor"></bean>

	<bean id="instantiationAwareBeanPostProcessor" class="com.freecloud.spring.lifecycle.MyInstantiationAwareBeanPostProcessor"></bean>

	<bean id="beanFactoryPostProcessor" class="com.freecloud.spring.lifecycle.MyBeanFactoryPostProcessor"></bean>

	<bean id="user" class="com.freecloud.spring.lifecycle.User" init-method="initMethod" destroy-method="destroyMethod" >
		<property name="name" value="張三"></property>
		<property name="age" value="18"></property>
	</bean>

</beans>

測試類:

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Author: maomao
 * @Date: 2021-04-18 20:57
 */
public class LifecycleTest {

    private ConfigurableApplicationContext applicationContext;

    @Before
    public void init(){
        applicationContext = new ClassPathXmlApplicationContext("application.xml");
    }


    @Test
    public void Test(){
        User user = applicationContext.getBean("user",User.class);
        //ConfigurableApplicationContext.close()將關閉該應用程序的上下文,釋放所有資源,并銷毀所有緩存的單例bean
        // 只用于destroy演示
        applicationContext.close();
        //applicationContext.registerShutdownHook();

        System.out.println("\n\n 輸出:" + user.getAge());
    }
}

最終結果:

Spring Bean有哪些生命周期

關于Spring Bean有哪些生命周期就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI