结合源码查看Spring容器以及Bean的初始化流程

Spring容器以及Bean初始化流程图

在这里插入图片描述

面试中常问的:Bean的生命周期?
其实就是如图所示bean开始初始化的流程。

本文不会很深入的去查看源码,能力有限。但是易于帮助理解Spring的初始化流程以及Bean的生命周期。

ClassPathXmlApplicationContext

从一个大家很熟悉的方法开始

ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Student student = context.getBean(Student.class);
System.out.println(student);

在执行new ClassPathXmlApplicationContext("bean.xml")代码的时候,其内部执行了如下的构造方法

public ClassPathXmlApplicationContext(
		String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
		throws BeansException {

	super(parent);
	// Set the config locations for this application context.
	setConfigLocations(configLocations);
	if (refresh) {
		refresh();
	}
}

记住这个refresh方法,spring容器的初始化全过程都集中的这个方面里面。

该文章基于xml配置文件的方式去创建bean以及演示,其实使用注解的方式也是差不多的。

refresh方法

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// 创建BeanFacory之前的准备工作
		prepareRefresh();

		// 创建BeanFactory,加载bean definitions也是其内部执行的
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// 在BeanFactory使用之前做一些准备工作,对BeanFactory的一些属性进行初始化
		prepareBeanFactory(beanFactory);

		try {
			// 如果我们自己实现了BeanFactoryPostProcessor中的postProcessBeanFactory方法,则执行(该方法本来就是一个空实现的方法,供我们去扩展)
			postProcessBeanFactory(beanFactory);

			// 实例化已注册的BeanFactoryPostProcessor对象(比如,spring内部实现的BeanFactoryPostProcessor对象),并且调用它们实现的postProcessBeanFactory方法
			invokeBeanFactoryPostProcessors(beanFactory);

			// 注册BeanPostProcessor
			registerBeanPostProcessors(beanFactory);
			
			// 以下四步都是在实例化bean之前做一些准备操作,它们不对bean做任何操作
			initMessageSource();
			initApplicationEventMulticaster();
			onRefresh();
			registerListeners();

			// 实例化bean(这里特指了实例化所有非懒加载的bean)
			finishBeanFactoryInitialization(beanFactory);

			// Last step: publish corresponding event.
			finishRefresh();
		}

		catch (BeansException ex) {
			if (logger.isWarnEnabled()) {
				logger.warn("Exception encountered during context initialization - " +
						"cancelling refresh attempt: " + ex);
			}

			// Destroy already created singletons to avoid dangling resources.
			destroyBeans();

			// Reset 'active' flag.
			cancelRefresh(ex);

			// Propagate exception to caller.
			throw ex;
		}

		finally {
			// Reset common introspection caches in Spring's core, since we
			// might not ever need metadata for singleton beans anymore...
			resetCommonCaches();
		}
	}
}

下面对一些重点方法进行分析。

obtainFreshBeanFactory

该方法中包括了创建BeanFactory、加载BeanDefinition等操作。

很好理解,在我们对bean进行正式的实例化、初始化操作时,首页你必须要一个IOC容器,也就是BeanFactory,其次,你必须要知道需要初始化的Bean的一些详细信息,这些详细信息就被封装在BeanDefinition中。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	// 创建BeanFactory
	refreshBeanFactory();
	// 返回BeanFactory
	return getBeanFactory();
}

refreshBeanFactory

protected final void refreshBeanFactory() throws BeansException {
	// 如果当前存在BeanFactory,则销毁掉,表示我们要重新创建一个新的
	if (hasBeanFactory()) {
		destroyBeans();
		closeBeanFactory();
	}
	try {
		// 创建BeanFactory方法,内部就是执行了new DefaultListableBeanFactory(getInternalParentBeanFactory())
		DefaultListableBeanFactory beanFactory = createBeanFactory();
		beanFactory.setSerializationId(getId());
		customizeBeanFactory(beanFactory);
		// 加载bean definitions
		loadBeanDefinitions(beanFactory);
		synchronized (this.beanFactoryMonitor) {
			this.beanFactory = beanFactory;
		}
	}
	catch (IOException ex) {
		throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
	}
}

loadBeanDefinitions:

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
	// 为给定的BeanFactory对象创建一个BeanDefinitionReader对象
	XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

	// Configure the bean definition reader with this context's
	// resource loading environment.
	beanDefinitionReader.setEnvironment(this.getEnvironment());
	beanDefinitionReader.setResourceLoader(this);
	beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

	// Allow a subclass to provide custom initialization of the reader,
	// then proceed with actually loading the bean definitions.
	initBeanDefinitionReader(beanDefinitionReader);
	// 加载bean definitions
	loadBeanDefinitions(beanDefinitionReader);
}

BeanDefinition:也就是我们定义的bean的一些信息,比如,bean的属性信息、class信息、name信息、是否是懒加载等。
在这里插入图片描述

从上面代码中可以看到,这里创建了一个XmlBeanDefinitionReader对象来加载bean definitions,不同的定义bean的方式会创建出不同的BeanDefinitionReader对象去读取bean definitions,这个也很好理解,比如我们可能不是用的xml的方式来配置定义bean的,而是使用properties配置文件,这个时候,你用XmlBeanDefinitionReader还能读取它里面定义的bean definition吗?

因此,BeanDefinitionReader提供了多种实现类:
在这里插入图片描述

XmlBeanDefinitionReader加载BeanDefinition的底层其实就是将xml文件解析成Document对象,然后读取这些标签信息,具体的细节并没有深入查看。

postProcessBeanFactory

点进去看一下,可以看到这个方式是个空方法
在这里插入图片描述
其实就是留给我们做一些扩展的,比如,你自己去实现了BeanFactoryPostProcessor中的postProcessBeanFactory方法,那么在这里就会被调用

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("invoke MyBeanFactoryPostProcessor...");
    }
}

invokeBeanFactoryPostProcessors

实例化已注册的BeanFactoryPostProcessor对象(比如,spring内部实现的BeanFactoryPostProcessor对象),并且调用它们实现的postProcessBeanFactory方法,根据情况完成一些特点的功能,比如下面讲的替换配置文件中${}占位符就是在这里完成的。

finishBeanFactoryInitialization

该方法主要调用了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.
	List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

	// Trigger initialization of all non-lazy singleton beans...
	for (String beanName : beanNames) {
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
			// 通过beanName判断该bean是一个FactoryBean还是普通Bean,如果是FactoryBean则会进入这个if
			if (isFactoryBean(beanName)) {
				Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
				if (bean instanceof FactoryBean) {
					final 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 {
				// 如果是普通bean,则直接调用这个方法
				getBean(beanName);
			}
		}
	}

	// Trigger post-initialization callback for all applicable beans...
	for (String beanName : beanNames) {
		Object singletonInstance = getSingleton(beanName);
		if (singletonInstance instanceof SmartInitializingSingleton) {
			final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
					smartSingleton.afterSingletonsInstantiated();
					return null;
				}, getAccessControlContext());
			}
			else {
				smartSingleton.afterSingletonsInstantiated();
			}
		}
	}
}

其核心方法就是这个getBean,实例化、初始化、循环依赖、注入属性等功能都是在这个方法里完成的,所以这个方法很重要。

该方法只调用了一个doGetBean方法。

贴一下其中的核心代码:

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) 
			throws BeansException {
			
	final String beanName = transformedBeanName(name);
	Object 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);
	}

	// ...

	// Create bean instance.
	if (mbd.isSingleton()) {
		sharedInstance = getSingleton(beanName, () -> {
			try {
				// 核心方法 创建bean
				return createBean(beanName, mbd, args);
			}
			catch (BeansException ex) {
				destroySingleton(beanName);
				throw ex;
			}
		});
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
	}
	
	// ...

}

该方法首先先去三级缓存中查询该对象是否存在,解决循环依赖的重要步骤之一,具体的可以看我的另一篇文章。

doCreateBean

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
		throws BeanCreationException {
	
	// Instantiate the bean.
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
		// 通过反射的方式去创建出这个bean的实例,也就是实例化bean
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	final Object bean = instanceWrapper.getWrappedInstance();
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}
	
	// ...
	
	
	// 此处也是解决循环依赖的重要步骤之一
	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");
		}
		// 将实例化好的bean放入三级缓存中
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}
	
	
	// 以下都属于bean的初始化过程(bean的生命周期从这里开始),注意是初始化,实例化在上面已经完成了
	Object exposedObject = bean;
	try {
		// 封装bean的一些属性,也就是调用set方法,在这一步之前,bean只是一个刚被实例化出来的空bean(啥属性都没封装)
		populateBean(beanName, mbd, instanceWrapper);
		// 初始化bean,调用PostProcessor以及init-method方法的过程,
		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.
	try {
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
	}
	
	return exposedObject;
}

createBeanInstance
通过反射的方式去实例化一个bean出来,其中又调用了instantiateBean方法来完成的。

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
	try {
		Object beanInstance;
		final BeanFactory parent = this;
		if (System.getSecurityManager() != null) {
			beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
					getInstantiationStrategy().instantiate(mbd, beanName, parent),
					getAccessControlContext());
		}
		else {
			// 根据beanName以及它的BeanDefinition获取到对应的实例化策略,完成bean的实例化
			beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
		}
		// ...
}

为了更清楚的看到,它是通过反射的方式创建的,这里就贴几个核心的代码

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
	if (!bd.hasMethodOverrides()) {
		Constructor<?> constructorToUse;
		synchronized (bd.constructorArgumentLock) {
			constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
			if (constructorToUse == null) {
				final Class<?> clazz = bd.getBeanClass();

				try {
					if (System.getSecurityManager() != null) {
						constructorToUse = AccessController.doPrivileged(
								(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
					}
					else {
						// 通过反射获取到当前class对象的构造器
						constructorToUse = clazz.getDeclaredConstructor();
					}
					bd.resolvedConstructorOrFactoryMethod = constructorToUse;
				}
			}
		}
		// 刚刚获取到的构造器对象传入这个方法中
		return BeanUtils.instantiateClass(constructorToUse);
	}
}
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
	if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
		return KotlinDelegate.instantiateClass(ctor, args);
	}
	else {
		Class<?>[] parameterTypes = ctor.getParameterTypes();
		Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");
		Object[] argsWithDefaultValues = new Object[args.length];
		for (int i = 0 ; i < args.length; i++) {
			if (args[i] == null) {
				Class<?> parameterType = parameterTypes[i];
				argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
			}
			else {
				argsWithDefaultValues[i] = args[i];
			}
		}
		// 看这里
		return ctor.newInstance(argsWithDefaultValues);
	}
}

constructorToUse = clazz.getDeclaredConstructor();
ctor.newInstance(argsWithDefaultValues);

populateBean
这个方法主要是对刚刚实例化出来的bean对象进行属性的注入,注意,在没有执行这一步之前,实例化出来的bean只是一个空对象,也就是一个任何属性都没有被初始化的空对象!

大家可以去观察一下,执行完这一步,它的属性值就会被赋值上去了。

initializeBean
接下来就是这个方法了。

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			invokeAwareMethods(beanName, bean);
			return null;
		}, getAccessControlContext());
	}
	else {
		// 当bean实现了Aware接口时,在这里会被调用对应的接口方法
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
		// 调用我们实现的postProcessBeforeInitialization方法(BeanPostProcessor接口)
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}

	try {
		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()) {
		// 调用我们实现的postProcessAfterInitialization方法(BeanPostProcessor接口)
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}

注意:
applyBeanPostProcessorsBeforeInitialization
applyBeanPostProcessorsAfterInitialization
这两个方法的返回值都是被增强后的对象(代理对象)。
比如,我们在自己实现BeanPostProcessor接口这两个方法时,上述方法的返回值就是我们return的对象(被增强后的对象)。

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("invoke postProcessBeforeInitialization defined by me");
        Student student = (Student) bean;
        student.setName("david");
        return student;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("invoke postProcessAfterInitialization defined by me");
        Student student = (Student) bean;
        student.setAge(10);
        return student;
    }
}

Q: xml配置文件中的${} 占位符是如何替换为实际的值的?什么时候被替换的?

比如,我在bean.xml文件里面编写了如下的代码

<context:property-placeholder location="db.properties"></context:property-placeholder>

<bean id="student" class="com.pri.spring5.demo.Student">
    <property name="name" value="${name}"></property> 			<!-- properties: name=rose -->
</bean>

Spring有很多内置的BeanFactoryPostProcessor的实现类,其中PropertySourcesPlaceholderConfigurer完成了这个功能
在这里插入图片描述

回想一下,在上述的spring初始化流程中,BeanPostFactory是在什么时候被调用的?

invokeBeanFactoryPostProcessors

验证:

首先我们在该方法上打一个断点,可以看到,在没有执行完该方法时,该bean的BeanDefinition中保存的属性信息依旧是一个未被替换值的占位符
在这里插入图片描述
该方法主要又调用了invokeBeanFactoryPostProcessors方法
在这里插入图片描述
执行到这行代码,你会发现,确实有一个PropertySourcesPlaceholderConfigurer被找到了。

然后去调用invokeBeanFactoryPostProcessors方法
在这里插入图片描述
很明显,该方法就是去调用我们实现的BeanFactoryPostProcessorpostProcessBeanFactory方法,所以,这里postProcessBeanFactory所实现的postProcessBeanFactory会被调用

进到它的postProcessBeanFactory方法里,找到下面这行代码
在这里插入图片描述

这里就不去细看了,里面调用了doProcessProperties方法,也就是将我们BeanDefinition中的占位符都替换为实际的值得操作。

执行完这个方法,你就会发现,原本保存BeanDefinition中的占位符会替换为我们定义在properties文件中的实际值了
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值