Spring 框架源码 Bean的生命周期全流程源码解析

Posted Dream_it_possible!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 框架源码 Bean的生命周期全流程源码解析相关的知识,希望对你有一定的参考价值。

        Spring框架作为Java王国的地基,我觉得它包含了很多精妙的设计,例如Bean工厂设计、Bean的生命周期、tx、aop、web、mvc等,最核心基本的Bean设计是Spring 的框架的灵魂,本文就Bean的生命周期全流程做源码程度上的解析,欢迎各位大佬指点江山。

        先上一张DefaultListableBeanFactory的UML图来来感受Spring 框架设计的强大,跟着DefaultListableBeanFactory去揭开Spring框架的核心面纱。

一、DefaultListableBeanFactory  

        DefaultListableBeanFactory掌管了Bean生命周期的大权,Bean的创建、初始化、销毁,添加BeanPostProcessor等功能,可以说是Spring框架最全的Bean工厂, 掌握DefaultListableBeanFactory 是非常有必要的。

1. 创建并注册BeanDefinition

        我们可以使用DefaultListableBeanFactory 对象注册一个BeanDefition, 使用registerBeanDefinition()方法, 如果想要加入一个BeanPostProcessor, 可以使用addBeanPostProcessor()方法。

	private DefaultListableBeanFactory createBeanByDefaultListableBeanFactory(final Class<?> beanClass) 
		DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
		RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
		beanDefinition.setInitMethodName("testMethod");
		beanDefinition.setDestroyMethodName("testDestroy");
		beanFactory.registerBeanDefinition("testBean", beanDefinition);
		//添加BeanPostProcessor
		beanFactory.addBeanPostProcessor(new BeanPostProcessor() 

			@Override
			public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException 
				//
				System.out.println("执行前..");
				return bean;
			

			@Override
			public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException 
				System.out.println("执行后..");
				return bean;
			
		);
		return beanFactory;
	

	public static class User 


		public void testMethod()
			System.out.println("初始化..");
		
		public void testDestroy()
			System.out.println("销毁..");
		
	

	@Test
	public void testDefaultListableBeanFactory() 
		final Class<?> beanClass = User.class;
		DefaultListableBeanFactory beanFactory = createBeanByDefaultListableBeanFactory(beanClass);
		User user = beanFactory.getBean("testBean", User.class);
		System.out.println("user= " + user);
		
	

打印结果:

从打印结果可以知道User这个Bean的三个方法的执行顺序: 

postProcessBeforeIntialization()> init-method()>postProcessAfterInitialization()

为了进一步理解Bean的生命周期,下面我们继续看Aware、BeanPostProcessor、InitialzingBean接口的执行顺序。 

2. 三级缓存设计

        DefaultListableBeanFactory里设计了三级缓存,三级缓存只针对单例Bean, 该三级缓存分别是: singletonObjects, earlySingletonObjects, singletonFactoirese。

/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

        有循环依赖的情况下获取Bean:

	/**
	 * Return the (raw) singleton object registered under the given name.
	 * <p>Checks already instantiated singletons and also allows for an early
	 * reference to a currently created singleton (resolving a circular reference).
	 * @param beanName the name of the bean to look for
	 * @param allowEarlyReference whether early references should be created or not
	 * @return the registered singleton object, or @code null if none found
	 */
	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) 
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) 
			synchronized (this.singletonObjects) 
				//尝试从二级缓存里
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) 
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) 
						// 从三级缓存里拿到ObjectFactory后,创建一个实例添加到二级缓存里
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					
				
			
		
		return singletonObject;
	

1. 先从一级缓存里拿, 如果有直接返回。

2. 如果从一级缓存里没有拿到Bean的实例,那么尝试从二级缓存里拿,如果有直接返回,没有执行步骤3.

3. 从三级缓存里根据BeanName获取到ObjectFactory接口实例,使用getObject()方法获取到实例后,加入到二级缓存同时返回实例。

        由于篇幅过长的问题,后续会单独写一篇Spring框架为什么要设计三级缓存,如果没有三级缓存能不能行?欢迎大家持续关注。

二、Bean的生命周期

BeanNameAware、BeanFactoryAware、BeanClassLoaderAware

        BeanNameAware、BeanFactoryAware、BeanClassLoaderAware接口分别是在初始化Bean之前调用的,我们可以利用BeanName、BeanFactory、ClassLoader去开发一些业务。

	/**
	 *  执行BeanNameAware、BeanClassLoaderAware、BeanFactoryAware的接口。
	 * @param beanName
	 * @param bean
	 */
	private void invokeAwareMethods(final String beanName, final Object bean) 
		if (bean instanceof Aware) 
			if (bean instanceof BeanNameAware) 
				((BeanNameAware) bean).setBeanName(beanName);
			
			if (bean instanceof BeanClassLoaderAware) 
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) 
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				
			
			if (bean instanceof BeanFactoryAware) 
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			
		
	

BeanPostProcessor在这里是在Aware之后调用的,接着看BeanPostProcessor接口。

BeanPostProcessor

        BeanPostProcessor接口里有2个默认方法,分别为PostProcessBeforeInitialization和PostProcessAfterInitialization。

public interface BeanPostProcessor 

	/**
	 * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
	 * initialization callbacks (like InitializingBean's @code afterPropertiesSet
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * <p>The default implementation returns the given @code bean as-is.
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one;
	 * if @code null, no subsequent BeanPostProcessors will be invoked
	 * @throws org.springframework.beans.BeansException in case of errors
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException 
		return bean;
	

	/**
	 * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
	 * initialization callbacks (like InitializingBean's @code afterPropertiesSet
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
	 * instance and the objects created by the FactoryBean (as of Spring 2.0). The
	 * post-processor can decide whether to apply to either the FactoryBean or created
	 * objects or both through corresponding @code bean instanceof FactoryBean checks.
	 * <p>This callback will also be invoked after a short-circuiting triggered by a
	 * @link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation method,
	 * in contrast to all other BeanPostProcessor callbacks.
	 * <p>The default implementation returns the given @code bean as-is.
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one;
	 * if @code null, no subsequent BeanPostProcessors will be invoked
	 * @throws org.springframework.beans.BeansException in case of errors
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
	 * @see org.springframework.beans.factory.FactoryBean
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException 
		return bean;
	


InitializingBean

        InitializingBean接口官方解释: 当所有的Bean属性被BeanFactory设置完后允许你用afterPropertieSet()方法做一次调。

/**
 * Interface to be implemented by beans that need to react once all their
 * properties have been set by a BeanFactory: for example, to perform custom
 * initialization, or merely to check that all mandatory properties have been set.
 *
 * <p>An alternative to implementing InitializingBean is specifying a custom
 * init-method, for example in an XML bean definition.
 * For a list of all bean lifecycle methods, see the
 * @link BeanFactory BeanFactory javadocs.
 *
 * @author Rod Johnson
 * @see BeanNameAware
 * @see BeanFactoryAware
 * @see BeanFactory
 * @see org.springframework.beans.factory.support.RootBeanDefinition#getInitMethodName
 * @see org.springframework.context.ApplicationContextAware
 */
public interface InitializingBean 

	/**
	 * Invoked by a BeanFactory after it has set all bean properties supplied
	 * (and satisfied BeanFactoryAware and ApplicationContextAware).
	 * <p>This method allows the bean instance to perform initialization only
	 * possible when all bean properties have been set and to throw an
	 * exception in the event of misconfiguration.
	 * @throws Exception in the event of misconfiguration (such
	 * as failure to set an essential property) or if initialization fails.
	 */
	void afterPropertiesSet() throws Exception;

该接口一般可以用来做属性实例的校验,比如当前Bean依赖了哪些Bean, 如果依赖的Bean没有初始化,就应该抛出异常,例如DataSourceTransactionManager里用该方法去校验DataSource有没有被初始化。



public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, InitializingBean 

	@Nullable
	private DataSource dataSource;

	private boolean enforceReadOnly = false;


	/**
	 * Create a new DataSourceTransactionManager instance.
	 * A DataSource has to be set to be able to use it.
	 * @see #setDataSource
	 */
	public DataSourceTransactionManager() 
		setNestedTransactionAllowed(true);
	

	/**
	 * Create a new DataSourceTransactionManager instance.
	 * @param dataSource JDBC DataSource to manage transactions for
	 */
	public DataSourceTransactionManager(DataSource dataSource) 
		this();
		setDataSource(dataSource);
		afterPropertiesSet();
	

	@Override
	public void afterPropertiesSet() 
		if (getDataSource() == null) 
			throw new IllegalArgumentException("Property 'dataSource' is required");
		
	


        InitializingBean接口的afterPropertiesSet()在AbstractAutowireCapableBeanFactoryinvokeInitMethods方法里被调用。

	protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable 

		boolean isInitializingBean = (bean instanceof InitializingBean);
		// 执行InitializingBean的afterPropertiesSet()
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) 
			if (logger.isDebugEnabled()) 
				logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
			
			if (System.getSecurityManager() != null) 
				try 
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> 
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					, getAccessControlContext());
				
				catch (PrivilegedActionException pae) 
					throw pae.getException();
				
			
			else 
				// 执行InitialingBean的afterProperties()接口。
				((InitializingBean) bean).afterPropertiesSet();
			
		

		if (mbd != null && bean.getClass() != NullBean.class) 
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) 
				invokeCustomInitMethod(beanName, bean, mbd);
			
		
	

三、AutowireCapableBeanFactory

四、AbstractAutowireCapableBeanFactory

        AbstarctAutowireCapableBeanFactory 是一个抽象类,实现了AutowireCapableBeanFactory和AbstarctBeanFactory接口,initializeBean方法实现了实例化Bean的整个流程。

	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 
			// 1. 执行所有的BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口,把对象塞入到参数里交给开发者使用。
			invokeAwareMethods(beanName, bean);
		
		// 2. 执行所有的BeanPostProcessor里的postProcessBeforeInitialization()
		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) 
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		

		try 
			// 3. 执行Init方法, 其中包含InitializingBean接口里的AfterPropertiesSet()方法和自定义的init()方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		
		catch (Throwable ex) 
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		
		//4. 执行所有的BeanPostProcessor的postProcessAfterInitialization()方法
		if (mbd == null || !mbd.isSynthetic()) 
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		

		return wrappedBean;
	

以上是关于Spring 框架源码 Bean的生命周期全流程源码解析的主要内容,如果未能解决你的问题,请参考以下文章

Spring源码解读---Bean生命周期源码解析

Spring源码解读---Bean生命周期源码解析

一文读懂Spring框架中Bean的生命周期

Spring 框架基础(02):Bean的生命周期,作用域,装配总结

浅谈Spring中Bean的生命周期

Spring Bean的生命周期