Spring源码解析之Bean的生命周期

一、Bean的实例化概述

前一篇分析了BeanDefinition的封装过程,最终将beanName与BeanDefinition以一对一映射关系放到beanDefinitionMap容器中,这一篇重点分析如何利用bean的定义信息BeanDefinition实例化bean。

二、流程概览

其实bean的实例化过程比较复杂,中间细节很多,为了抓住重点,先将核心流程梳理出来,主要包含以下几个流程:

  • step1: 通过反射创建实例;
  • step2:给实例属性赋初始值;
  • step3:如果Bean类实现BeanNameAware接口,则将通过传递Bean的名称来调用setBeanName()方法;如果Bean类实现BeanClassLoaderAware接口,则将通过传递加载此Bean的ClassLoader对象的实例来调用setBeanClassLoader()方法;如果Bean类实现BeanFactoryAware接口,则将通过传递BeanFactory对象的实例来调用setBeanFactory()方法;
  • step4: 如果有类实现BeanPostProcessors接口,则将在初始化之前调用postProcessBeforeInitialization()方法;
  • step5:如果Bean类实现了InitializingBean接口,将调用afterPropertiesSet()方法,如果配置文件中的Bean定义包含init-method属性,则该属性的值将解析为Bean类中的方法名称,并将调用该方法;
  • step6: 如果有类实现BeanPostProcessors接口,则将在初始化之后调用postProcessAfterInitialization()方法;
  • step7:如果Bean类实现DisposableBean接口,则当Application不再需要Bean引用时,将调用destroy()方法;如果配置文件中的Bean定义包含destroy-method属性,那么将调用Bean类中的相应方法定义。

三、源码分析

进入AbstractApplicationContext中的fresh()方法,找到finishBeanFactoryInitialization(beanFactory)方法,该类是bean的实例化的入口,具体的实例化由preInstantiateSingletons()方法触发,见如下代码:

public void preInstantiateSingletons() throws BeansException
  if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		//xml解析时,把所有beanName都缓存到beanDefinitionNames了
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			//把父BeanDefinition里面的属性拿到子BeanDefinition中
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			//如果不是抽象的,单例的,非懒加载的就实例化
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				//判断bean是否实现了FactoryBean接口
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(
									(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
					// 实例化过程
					getBean(beanName);
				}
			}
		}

上述代码主要看getBean方法,随后进入doGetBean方法:

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {

		String beanName = transformedBeanName(name);
		Object bean;

		// 从缓存中获取bean.
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						registerDependentBean(dep, beanName);
						try {
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				// Create bean instance
                                // 创建bean实例
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
...
}

由上述代码可知,先从缓存中获取bean,如果没有,则创建bean,最重要的方法就是getSingleton,该方法第二个参数是个函数式接口,进入getSingleton方法,当调用singletonObject = singletonFactory.getObject()时,会触发函数式接口中的createBean方法,随后一路进入doCreateBean,这个方法里面完成了所有实例化所需的步骤:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		// 真正开始创建bean的实例.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			// 属性赋值
			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);
			}
		}

		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
                // 有必要时,注册bean的销毁
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

从上述源码中看出bean的实例化主要分为以下三步:

  • step1:bean的创建;
  • step2:给bean的属性赋值;
  • step3:bean的初始化;

接着得到exposedObject这个已经完全实例化后的bean返回,其中当有必要时,注册bean的销毁,后面再详细看,先抓住主要流程。其中step3也是比较重要的方法,进入该方法:

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			// 激活aware接口
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			// 初始化前处理的beanPostProcessor
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			// 激活 init-method方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			// 初始化后处理的beanPostProcessor
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

从上面源码可知,梳理出主要的四个步骤:

  • step1:激活aware接口,完成aware接口的相关操作;
  • step2:初始化前处理的beanPostProcessor;
  • step3:完成init-method方法;
  • step4:初始化后处理的beanPostProcessor;

BeanPostProcessor作用是对初始化后的bean进行增强处理,在该阶段 BeanPostProcessor 会处理当前容器内所有符合条件的实例化后的 bean 对象。它主要是对 Spring 容器提供的 bean 实例对象进行有效的扩展,允许Spring在初始化 bean 阶段对其进行定制化修改,如处理标记接口或者为其提供代理实现。

四、演示

定义一个MyBeanPostProcessor实现BeanPostProcessor接口

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("post Process Before Initialization 被调用...");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("post Process after Initialization 被调用...");
        return bean;
    }
}

定义一个LifeCycleBean类,实现如下接口:

public class LifeCycleBean implements BeanNameAware, BeanFactoryAware, BeanClassLoaderAware,
        InitializingBean, DisposableBean {

    private String property;

    public String getProperty() {
        return property;
    }

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

    public LifeCycleBean(){
        System.out.println("构造函数调用...");
    }
    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("BeanClassLoaderAware 被调用...");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactoryAware 被调用...");
    }

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

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

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

    public void initMethod(){
        System.out.println("init-method 被调用...");
    }

    public void destroyMethod(){
        System.out.println("destroy-method 被调用...");
    }

    public void display(){
        System.out.println("方法调用...");
    }

}

指定配置文件spring.xml,配置init-methoddestroy-method方法

<bean id="lifeCycle" class="com.wzj.bean.LifeCycleBean"
		  init-method="initMethod" destroy-method="destroyMethod">
		<property name="property" value="property"/>
	</bean>
	<bean id="myBeanPostProcessor" class="com.wzj.bean.MyBeanPostProcessor" >
	</bean>

测试类如下:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring.xml"})
public class TestSpring {

    @Test
    public void testLifeCycleBean() {
	    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");

    }

执行结果:

构造函数调用...
属性注入....
BeanNameAware 被调用...
BeanClassLoaderAware 被调用...
BeanFactoryAware 被调用...
post Process Before Initialization 被调用...
InitializingBean afterPropertiesSet 被调用...
init-method 被调用...
post Process after Initialization 被调用...
DisposableBean destroy 被调用...
destroy-method 被调用...

五、总结

本篇从一个初学者的角度概览了bean的整个生命周期,并描述了其中的主要流程,阅读源码的初始阶段,优先抓住主要流程,别陷入细节,并通过跑案例、写注解、画流程图等方式加深理解,后续将继续分析bean实例化中的核心流程、设计思想等。

到此这篇关于Spring源码解析之Bean的生命周期的文章就介绍到这了,更多相关Bean的生命周期内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Spring中bean的生命周期之getSingleton方法

    Spring中bean的生命周期 要想讲清楚spring中bean的生命周期,真的是不容易,以AnnotationConfigApplicationContext上下文为基础来讲解bean的生命周期,AnnotationConfigApplicationContext是基于注解的上下文,使用XML的方式现在很少见,所以以此上下文为基础,使用XML的上下文ClassPathXmlApplicationContext的步骤和AnnotationConfigApplicationContext类似.

  • 详解Spring中Bean的作用域与生命周期

    目录 一.Bean的作用域 二.Bean的生命周期 使用代码演示Bean的生命周期 一.Bean的作用域 通过Spring容器创建一个Bean的实例时,不仅可以完成Bean的实例化,还可以使用Bean的scope属性为bean设置作用域. 语法格式:<bean id="别名" scope="作用域" class="对应实现类"> 作用域的种类:(sing) singleton和prototype区别:(该两种比较常用) ① singl

  • Spring中Bean的作用域与生命周期详解

    目录 一.Bean的作用域 1.单实例Bean声明 2.多实例Bean声明 二.Bean的生命周期 1.bean的初始和销毁 2.bean的后置处理器 总结 一.Bean的作用域 首先我们来讲一下有关于bean的作用域, 一般情况下,我们书写在IOC容器中的配置信息,会在我们的IOC容器运行时被创建,这就导致我们通过IOC容器获取到bean对象的时候,往往都是获取到了单实例的Bean对象, 这样就意味着无论我们使用多少个getBean()方法,获取到的同一个JavaBean都是同一个对象,这就是

  • Java之SpringBean生命周期问题理解

    Spring Bean的生命周期? 首先说一下Servlet的生命周期:实例化,初始init,接收请求service,销毁destroy: Spring上下文中的Bean生命周期也类似,如下: (1)实例化Bean: 对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化.对于ApplicationContext容器,当容器启动结束后,通过获取BeanDefinition对象中

  • Java Spring Bean的生命周期管理详解

    目录 Spring Bean的生命周期管理 一.Spring Bean的生命周期 二.通过@Bean的参数(initMethod ,destroyMethod)指定Bean的初始化和销毁方法 1.项目结构 2.Person 3.Bean注册配置类(单实例) 4.测试类 5.测试结果 6.Bean注册配置类(多实例) 7.测试结果 三.Bean实现接口InitializingBean, DisposableBean 1.Person 2.Bean注册配置类 3.测试结果 四.通过注解@PostCo

  • Java Spring循环依赖原理与bean的生命周期图文案例详解

    前言 Spring是如何处理循环依赖的,又是怎么做到,互相注入对方的proxy bean而不是raw bean的?现在就分析一下 一.循环依赖是什么 Spring中放入两个Service,分别是C1和C2,然后C1和C2又互为对方的成员变量.这种情况C1和C2就可以说是相互循环依赖了 二.源码图解 1. bean的主要生命周期图解 上图是一个没有循坏依赖的bean的主要生命周期节点,下图的循坏依赖可以结合该图解一起看 2.循环依赖图解 可以看到里面有一个很重要的逻辑: 当一个bean经过所有的步

  • Spring源码解析之Bean的生命周期

    一.Bean的实例化概述 前一篇分析了BeanDefinition的封装过程,最终将beanName与BeanDefinition以一对一映射关系放到beanDefinitionMap容器中,这一篇重点分析如何利用bean的定义信息BeanDefinition实例化bean. 二.流程概览 其实bean的实例化过程比较复杂,中间细节很多,为了抓住重点,先将核心流程梳理出来,主要包含以下几个流程: step1: 通过反射创建实例: step2:给实例属性赋初始值: step3:如果Bean类实现B

  • Spring源码解析 Bean属性填充

    目录 前言 属性填充 执行回调方法及后置处理器 前言 在上一篇文章中,我们分析了Spring中Bean的实例化过程,在结尾我们知道了虽然bean的实例化完成了,但是其中的属性还没有被注入,今天我们就接着来分析属性是如何被注入的. 属性填充 实例化完成后,回到上面第3条的doCreateBean方法中,看一下用BeanWrapper产生的原生对象,里面dao这个属性还是null值. 回归一下之前的代码,接下来要调用populateBean方法进行属性的填充: Object exposedObjec

  • Spring源码解析 Bean的实例化

    目录 前言 准备工作 实例化bean 1.AbstractBeanFactory 的 doGetBean方法 2.AbstractAutowireCapableBeanFactory 的 createBean方法 3.AbstractAutowireCapableBeanFactory 的 doCreateBean方法 4.AbstractAutowireCapableBeanFactory 的 createBeanInstance方法 5.AbstractAutowireCapableBean

  • Spring源码解析之Configuration

    一.@Configuration 1.1 未加@Configuration <!--logback-test.xml,配置不打印日志--> <?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/base.xml" /> <

  • Spring源码解析后置处理器梳理总结

    目录 前言 1.InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()方法 2.SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors()方法 3.MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition()方法 4.SmartInstantiationA

  • spring源码学习之bean的初始化以及循环引用

    实例化方法,把bean实例化,并且包装成BeanWrapper 1.点进这个方法里面. 这个方法是反射调用类中的 factoryMethod 方法. 这要知道@Bean 方法的原理, 实际上spring 会扫描有@bean 注解的方法, 然后把方法名称设置到 BeanDefinition 的 factoryMethod属性中, 接下来就会调到上面截图中的方法实现@Bean 方法的调用. 2. 有参构造函数的时候 determineConstructorsFromBeanPostProcessor

  • Spring源码解析之BeanPostProcessor知识总结

    一.简介 BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口. 实例化Bean做前置处理.后置处理 二.接口定义 @Component public class BeanPost implements BeanPostProcessor { /** * 在每个bean创建之后的初始化方法之前调用 * @param bean 当前实例化的bean * @param beanName bean的名称 * @return 返回实例化的bean或者可以对对象进行再封装返

  • Spring源码解析之推断构造方法

    Spring推断构造方法 贴个测试代码直接开干,这只是个样例,其他情况自行分析 @Component public class OrderService { public OrderService() { System.out.println("无参构造方法"); } @Autowired(required = false) public OrderService(UserService userService) { System.out.println("一个参数的构造方法

  • Spring源码解析之编程式事务

    一.前言 在Spring中,事务有两种实现方式: 编程式事务管理: 编程式事务管理使用TransactionTemplate可实现更细粒度的事务控制.声明式事务管理: 基于Spring AOP实现.其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务. 声明式事务管理不需要入侵代码,通过@Transactional就可以进行事务操作,更快捷而且简单(尤其是配合spring boot自动配置,可以说是精简至极!),且大部分业务都可

  • 从Spring源码解析事务失效的原因

    目录 一.前言 二.方法不是 public 的 三.内部方法间调用导致事务失效 四.异常类型是否配置正确 五.异常被catch住 一.前言 1.Bean是否是代理对象 2.入口函数是否是public的 3.数据库是否支持事务(Mysql的Mvlsam不支持事务),行锁才支持事务 4.切点是否配置正确 5.内部方法间调用导致事务失效 因为this不是代理对象,可以配置 expose-proxy="true",就可以通过AopContext.currentProxy()获取到当前类的代理对

随机推荐