Spring IOC源碼分析三:Spring refresh下-實例化bean

7.initMessageSource

在Spring容器中初始化一些國際化相關的屬性。

8.initApplicationEventMulticaster

在Spring容器中初始化事件廣播器,事件廣播器用於事件的發佈。

9.onRefresh

一個模板方法,不同的Spring容器做不同的事情。

比如web程序的容器AnnotationConfigEmbeddedWebApplicationContext中會調用createEmbeddedServletContainer方法去創建內置的Servlet容器,如啓動tomcat。

10.registerListeners

把Spring容器內的時間監聽器和BeanFactory中的時間監聽器都添加的事件廣播器中。

11.finishBeanFactoryInitialization

實例化BeanFactory中已經被註冊但是未實例化的所有非懶加載實例
主流程

在這裏插入圖片描述
主流程大致爲,從緩存中找到是否已經實例化了該 singleton bean,如果已經實例化好了,那麼就直接返回;如果在緩存中沒有找到,則將當前的 bean 封裝爲 RootBeanDefinition,然後通過調用 DefaultSingletonBeanRegistry#getSingleton 得到初始化好的 singleton bean,然後將其註冊至緩存,然後再判斷是普通 bean 還是 factory bean 作必要的處理後,最後返回。

AbstractBeanFactory#doGetBean

 Object sharedInstance = getSingleton(beanName);

先從緩存中查找是否以及實例化了該bean,如果已存在,直接返回。

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

將當前bean標記爲已創建。

if (mbd.isSingleton()) {
	sharedInstance = getSingleton(beanName, () -> {
		try {
			//回調AbstractAutowireCapableBeanFactory 的 createBean
			return createBean(beanName, mbd, args);
		}
		catch (BeansException ex) {
			destroySingleton(beanName);
			throw ex;
		}
	});
	bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

這裏調用DefaultSingletonBeanRegistry#getSingleton:

beforeSingletonCreation(beanName);
singletonObject = singletonFactory.getObject();
afterSingletonCreation(beanName);
if (newSingleton) {
    addSingleton(beanName, singletonObject);
}

beforeSingletonCreation和afterSingletonCreation 檢查了當前bean是不是在被排除的bean集合中以及是不是正在創建。

protected void beforeSingletonCreation(String beanName) {
	if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
		throw new BeanCurrentlyInCreationException(beanName);
	}
}

protected void afterSingletonCreation(String beanName) {
	if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
		throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
	}
}

而addSingleton是將實例化好的bean加入緩存
接下來重點關注singletonObject = singletonFactory.getObject(),這裏回調了getObject方法,即AbstractAutowireCapableBeanFactory#createBean。通過此回調方法正式拉開了實例化 bean 的序幕。
AbstractAutowireCapableBeanFactory#createBean

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
	return bean;
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);

在進行真正的實例化之前,會先調用一部分已註冊的beanPostProcessor的before,after方法。
AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation

Class<?> targetType = determineTargetType(beanName, mbd);
	if (targetType != null) {
		bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
		if (bean != null) {
			bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
		}
}

AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation

for (BeanPostProcessor bp : getBeanPostProcessors()) {
	if (bp instanceof InstantiationAwareBeanPostProcessor) {
		InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
		Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
		if (result != null) {
			return result;
		}
	}
}

可以看出,這裏只處理實現了InstantiationAwareBeanPostProcessor的processor,如AbstractAutoProxyCreator,用來處理AOP。

從主流程可以看出主要做了三件事:一、create Bean Instance;二、populate bean;三、initialize bean。

create Bean Instance

createBeanInstance根據 bean 的不同配置方式,實現了三種實例化bean的方式,分別是 factory instantiate bean、autwire instantiate bean 以及 default instantiate bean。
AbstractAutowireCapableBeanFactory#createBeanInstance

instantiateUsingFactoryMethod(beanName, mbd, args);
autowireConstructor(beanName, mbd, ctors, null);
instantiateBean(beanName, mbd);
factory instantiate bean

ConstructorResolver#instantiate

this.beanFactory.getInstantiationStrategy().instantiate(mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args)

SimpleInstantiationStrategy#instantiate

Object result = factoryMethod.invoke(factoryBean, args);
if (result == null) {
	result = new NullBean();
}
return result;

通過反射調用FactoryMethod實例化bean

autwire instantiate bean

ConstructorResolver#instantiate

private Object instantiate(
	String beanName, RootBeanDefinition mbd, Constructor constructorToUse, Object[] argsToUse) {
	InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
	return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
	
}
	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
			final Constructor<?> ctor, Object... args) {

		if (!bd.hasMethodOverrides()) {
			if (System.getSecurityManager() != null) {
				// use own privileged to change accessibility (when security is on)
				AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
					ReflectionUtils.makeAccessible(ctor);
					return null;
				});
			}
			return BeanUtils.instantiateClass(ctor, args);
		}
	}

SimpleInstantiationStrategy#instantiate

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
			final Constructor<?> ctor, Object... args) {
	return BeanUtils.instantiateClass(ctor, args);
}
//instantiateClass
ctor.newInstance(args);
//newInstance
T inst = (T) ca.newInstance(initargs);

這裏也是通過使用其構造函數 constructor 使用Java 反射實例化了 bean。

default instantiate bean

AbstractAutowireCapableBeanFactory#instantiateBean

beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);

SimpleInstantiationStrategy#instantiate

BeanUtils.instantiateClass(constructorToUse);
//instantiateClass
ctor.newInstance(args);
//newInstance
T inst = (T) ca.newInstance(initargs);

這裏僅僅是通過使用其構造函數 constructor 使用Java 反射實例化了 bean,並沒有對其進行任何的參數賦值

populate bean

AbstractAutowireCapableBeanFactory#populateBean

if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
	MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
	// Add property values based on autowire by name if applicable.
	if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
		autowireByName(beanName, mbd, bw, newPvs);
	}
	// Add property values based on autowire by type if applicable.
	if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
		autowireByType(beanName, mbd, bw, newPvs);
	}
	pvs = newPvs;
}

進行依賴注入的過程,先處理autowire的注入,可以根據Bean的名字或類型來完成Bean的autowire

if (pvs != null) {
	//對屬性進行注入 例如feign
	applyPropertyValues(beanName, mbd, bw, pvs);
}

然後對屬性進行注入。通過這一步,將相關的 property populate 給 bean 以後,纔算 bean 的實例化完成。

initialize bean

AbstractAutowireCapableBeanFactory#initializeBean

	protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		invokeAwareMethods(beanName, bean); ①
		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			//執行bean-post-processor 的beforeInitialization方法
			wrappedBean = applyBeanPostProcessorsBeforeInitialization (wrappedBean, beanName);}

		try {
			//處理實現了InitializingBean接口的beans的回調方法
			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()) {
			//執行bean-post-processor 的afterInitialization方法
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}

		return wrappedBean;
	}

整個流程可以理解爲三大塊

  1. 注入 Aware 對象,見①;
  2. 調用 bean-post-processors 接口方法,見②和④;
  3. 調用 InitializingBean 方法,見③。
注入 Aware 對象

AbstractAutowireCapableBeanFactory#invokeAwareMethods

	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);
				}
			}
			//將當前的beanFactory注入,這也就是爲什麼如果實現了BeanFactoryAware接口,會自動獲取到但錢的BeanFactory實例
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

可以看到,注入了三種情況

  • 如果當前 bean 實現了 BeanNameAware 接口,只是調用了 setBeanName,比如logging
  • 如果當前 bean 實現了 BeanClassLoaderAware 接口,將 Spring 容器的 BeanClassLoader 注入到當前 bean
  • 如果當前 bean 實現了 BeanFactoryAware 接口,將 Spring 容器中與 bean 初始化相關的 BeanFactory 實例註冊給當前的 bean。
調用 bean-post-processors 接口方法
	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

可以看出如果某個 beanProcessor 處理返回一個 null 則直接返回,並且終止其餘的 bean-post-processors。要注意的是,該回調方法是針對對容器中所有的普通 bean 進行的回調。並且該方法是在回調 InitializeBean 接口方法之前調用,並且是在 populate bean之後進行的調用,通常是對原有 bean 做一層封裝,然後返回該封裝對象。這點BeanPostProcessor接口註釋也已經說明。

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.
     * @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
     */
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    /**
     * 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.
     * @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
     */
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}
調用 InitializingBean 方法
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
        throws Throwable {

    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isDebugEnabled()) {
            logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        .....
        ((InitializingBean) bean).afterPropertiesSet();
        .....
    }

    if (mbd != null) {
        String initMethodName = mbd.getInitMethodName();
        if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

可以看到,主要回調的是InitializingBean接口的afterPropertiesSet方法,所以,我們可以讓某個 bean 實現 InitializingBean 接口,並通過該接口實現一些當 bean 實例化好以後的回調方法,注意afterPropertiesSet並不返回任何值,所以,這裏不是像 bean-post-processor 那樣對 bean 起到修飾的作用,而是起到純粹的調用作用

12.finishRefresh

refresh做完之後需要做的其他事情。

  1. 清除上下文級資源緩存(例如來自掃描的ASM元數據)。
  2. 初始化生命週期處理器,並設置到Spring容器中(LifecycleProcessor)
  3. 調用生命週期處理器的onRefresh方法,這個方法會找出Spring容器中實現了SmartLifecycle接口的類並進行start方法的調用
  4. 發佈ContextRefreshedEvent事件告知對應的ApplicationListener進行響應的操作
  5. 發佈EmbeddedServletContainerInitializedEvent事件告知對應的ApplicationListener進行響應的操作
  6. 調用LiveBeansView的registerApplicationContext方法:如果設置了JMX相關的屬性,則就調用該方法

擴展

到這裏Spring 容器的bean初始化就全部完成了,最後補充一個擴展,那就是ApplicationContext是在什麼時候注入的,從上述文章不難看出,invokeAwareMethods並沒有對ApplicationContext注入,經過測試發現,如果實現了ApplicationContextAware,則將會在調用 bean-post-processors 接口方法這一步的postProcessBeforeInitialization中的invokeAwareInterfaces方法進行注入
ApplicationContextAwareProcessor

    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;
        
        ....

        invokeAwareInterfaces(bean);

        ....

        return bean;
    }

    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
            }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

  
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }

以上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章