• 小米面试官:说说Spring源码里面的Bean的生命周期!


    1. Bean的实例化概述

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

    Spring学习笔记地址:Spring核心170多页学习笔记

    2. 流程概览

    其实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类中的相应方法定义。

    3. 源码分析

    进入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 阶段对其进行定制化修改,如处理标记接口或者为其提供代理实现。

    4. 演示

    定义一个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-method与destroy-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 被调用...
    

    4. 总结

    本篇从一个初学者的角度概览了bean的整个生命周期,并描述了其中的主要流程,阅读源码的初始阶段,优先抓住主要流程,别陷入细节,并通过跑案例、写注解、画流程图等方式加深理解,后续将继续分析bean实例化中的核心流程、设计思想等,需要Spring源码学习笔记+知识点总结思维导图+Spring相关面试真题可以关注工中号:麒麟改bug 获取。

  • 相关阅读:
    浅谈缓存管理
    [Architecture Pattern] Database Migration (上)
    knockout.js的学习笔记4
    cenOS5.5安装oracle10g(傻瓜篇)
    SportsStore:管理 — 精通ASP.NET MVC 3
    ASP.NET MVC下的异步Action的定义和执行原理
    基于EF 4.3.1 Code First的领域驱动设计实践案例
    asp.net缓存
    《Pro ASP.NET MVC 3 Framework》部署
    Asp.Net MVC 3.0【Hello World!】
  • 原文地址:https://www.cnblogs.com/QLCZ/p/14958802.html
Copyright © 2020-2023  润新知