ApplicationContext和Bean的初始化及销毁
对于BeanFactory,特别是ApplicationContext,容器自身也有一个初始化及销毁关闭的过程。
ApplicationContext启动的过程是在AbstractApplicationContext中实现的,在这之前需要一些准备工作prepareBeanFactory()
方法实现,这个方法中为容器配置了ClassLoader、PropertyEditor和BeanPostProcessor等,为容器启动做好了必要的准备工作。
/**
* 配置工厂的标准上下文特征,例如上下文的ClassLoader和后处理器。
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
* @param beanFactory the BeanFactory to configure
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
if (!shouldIgnoreSpel) {
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartup.class);
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (!IN_NATIVE_IMAGE && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}
同样在容器要关闭时,也需要完成一系列工作,这些工作在doClose方法中完成,这个方法中先发出容器关闭的信息,然后将Bean逐个关闭,最后关闭容器自身。
protected void doClose() {
// Check whether an actual close attempt is necessary...
if (this.active.get() && this.closed.compareAndSet(false, true)) {
if (logger.isDebugEnabled()) {
logger.debug("Closing " + this);
}
if (!IN_NATIVE_IMAGE) {
LiveBeansView.unregisterApplicationContext(this);
}
try {
// Publish shutdown event.
publishEvent(new ContextClosedEvent(this));
}
catch (Throwable ex) {
logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
}
// Stop all Lifecycle beans, to avoid delays during individual destruction.
if (this.lifecycleProcessor != null) {
try {
this.lifecycleProcessor.onClose();
}
catch (Throwable ex) {
logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
}
}
// Destroy all cached singletons in the context's BeanFactory.
// 销毁上下文的BeanFactory中所有缓存的单例。
destroyBeans();
// Close the state of this context itself.
// 关闭此上下文本身的状态。
closeBeanFactory();
// Let subclasses do some final clean-up if they wish...
onClose();
// Reset local application listeners to pre-refresh state.
if (this.earlyApplicationListeners != null) {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Switch to inactive.
this.active.set(false);
}
}
容器的实现是通过IoC管理Bean的生命周期来实现的,Spring IoC容器在对Bean的生命周期进行管理时提供了Bean生命周期各个时间点的回调。
IoC容器中Bean的声明周期
- Bean实例的创建;
- 为Bean实例设置属性;
- 调用Bean的初始化方法;
- 应用可以通过IoC容器使用Bean;
- 容器关闭时,调用Bean的销毁方法。
/**
* 初始化给定的bean实例,应用工厂回调以及init方法和bean post处理器。
*/
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 {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
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()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
在调用Bean初始化方法之前,会调用一系列aware接口实现,在invokeInitMethods
方法中实现。
/**
* 将相关的BeanName、BeanClassLoader以及BeanFactory注入到Bean中
* @param beanName
* @param bean
*/
private void invokeAwareMethods(String beanName, 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);
}
}
}
接下来,调用Bean的初始化方法,最后还会看到判断Bean是否配置有initMethod,如果有,则通过调用invokeCustomInitMethod
方法来直接调用,最终完成Bean的初始化。
/**
* 在给定的bean上调用指定的自定义init方法。
*/
protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd)
throws Throwable {
String initMethodName = mbd.getInitMethodName();
Assert.state(initMethodName != null, "No init method set");
Method initMethod = (mbd.isNonPublicAccessAllowed() ?
BeanUtils.findMethod(bean.getClass(), initMethodName) :
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
if (initMethod == null) {
if (mbd.isEnforceInitMethod()) {
throw new BeanDefinitionValidationException("Could not find an init method named '" +
initMethodName + "' on bean with name '" + beanName + "'");
}
else {
if (logger.isTraceEnabled()) {
logger.trace("No default init method named '" + initMethodName +
"' found on bean with name '" + beanName + "'");
}
// Ignore non-existent default lifecycle methods.
return;
}
}
if (logger.isTraceEnabled()) {
logger.trace("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
}
Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod);
// 得到initMethod,通过反射机制得到Method对象 直接调用在Bean定义中声明的初始化方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(methodToInvoke);
return null;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
() -> methodToInvoke.invoke(bean), getAccessControlContext());
}
catch (PrivilegedActionException pae) {
InvocationTargetException ex = (InvocationTargetException) pae.getException();
throw ex.getTargetException();
}
}
else {
try {
ReflectionUtils.makeAccessible(methodToInvoke);
methodToInvoke.invoke(bean);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
lazy-init属性和预实例化
除了在IoC初始化过程中使用getBean()向容器索要Bean时会发生依赖注入之外,也有一种例外情况,就是用户可以通过设置Bean的lazy-init属性来控制预实例化的过程。
这个预实例化在初始化容器时完成Bean的依赖注入,虽然这种容器的使用方式会对容器初始化性能有一些影响,但却能够提高应用第一次取得Bean的性能。
初始化上下文是refresh()
方法中的一个步骤,下面从lazy-init属性配置实现的角度进行分析,这个属性的处理也是refresh()
的一部分。
在finishBeanFactoryInitialzation
的方法中,封装了对lazy-init属性的处理,实际的处理是在DefaultListableBeanFactory
的preInstantiateSingletons
方法中完成的,该方法对单例Bean完成预实例化。这个预实例化的完成巧妙地委托给容器来实现,如果需要预实例化那么就直接在这里采用getBean去触发依赖注入,与正常依赖注入相比,只有触发的时间和场合不同。在这里,依赖注入发生在容器执行refresh的过程中,也就是发生在IoC容器初始化的过程中,而不像一般的依赖注入一样发生在IoC容器初始化完成后。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 实例化所有的非延迟化单例Bean
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
destroyBeans();
cancelRefresh(ex);
throw ex;
}
finally {
resetCommonCaches();
contextRefresh.end();
}
}
}
/**
* 完成此上下文的BeanFactory的初始化,初始化所有剩余的单例bean。
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 如果有需要进行服务转换的Bean 则进行类型转换
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
beanFactory.setTempClassLoader(null);
beanFactory.freezeConfiguration();
// 调用BeanFactory的preInstantiateSingletons,这个方法由DefaultListableBeanFactory实现
beanFactory.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.
// 遍历一个副本以允许使用init方法,这些方法依次注册新的bean定义。
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 判断BeanFactory中的BeanDefinition 是否满足:1、非抽象 2、单例Bean 3、非延迟初始化
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
/**
* 和正常依赖注入过程一样,只是发生的地方不同。同样会对BeanDefinitionMap
* 中所有的Bean进行依赖注入,这样在初始化过程结束后,容器执行getBean得到
* 的就是已经准备好的Bean不需要进行依赖注入
*/
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);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}
可以通过lazy-init属性来对整个IoC容器的初始化和依赖注入过程进行一些简单控制,这个控制是可以由容器的使用者来决定的。具体地说,可以通过在BeanDefination中设置lazy-init属性并来控制。
FactoryBean的实现
FactoryBean为应用生成需要的对象,这些对象往往是经过特殊处理的。FactoryBean的生产特性是在getBean中起作用的。
/**
* 获取给定bean实例的对象,可以是bean实例本身,也可以是FactoryBean创建的对象。
*/
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 如果这里不是对FactoryBean的调用,那么结束处理
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// 如果是一个FactoryBean,则使用它创建一个Bean实例,除非调用者想引用它作为一个工厂
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
// 获取FactoryBean的实例
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 这里从FactoryBean中得到Bean
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
return object;
}
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 这里调用factory的getObject 方法来从FactoryBean中得到Bean
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}
这里返回的已经是作为工厂FactoryBean生产的产品,而不是FactoryBean本身。这种FactoryBean的机制可以为我们提供一个很好地封装机制,如封装Proxy、RMI、JNDI等。
getObject方法就是主要的FactoryBean的接口,需要实现特定的工厂的生产过程。
BeanPostProcessor的实现
BeanPostProcessor是一个监听器,可以监听容器触发的事件。将它向IoC容器注册后,容器中管理的Bean具备了接收IoC容器事件回调的能力。
BeanPostProcessor的使用非常简单,设计一个具体的后置处理器来实现,同时这个具体的后置处理器需要实现接口类BeanPostProcessor,然后设置到XML的Bean配置文件中。
BeanPostProcessor是一个接口类:
public interface BeanPostProcessor {
/**
* 在Bean的初始化前提供回调入口
*/
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
/**
* 在Bean初始化后提供回调入口
*/
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
这两个回调的处罚都是和容器管理Bean的生命周期相关的,参数都是Bean的实例化对象和Bean的名字。
postProcessorBeforeInitialization
是在populateBean完成之后被调用的,从BeanPostProcessor中的一个回调接口入手,对另一个回调接口PostProcessorAfterInitialization
方法的调用。在populateBean方法中的initializeBean调用。
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
// 在完成对Bean的生成和依赖注入后,开始对Bean初始化
// 这份初始化过程包含了对后置处理器的回调
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
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 {
invokeAwareMethods(beanName, bean);
}
// 这里是对后置处理器BeanPostProcessors的PostProcessBeforeInitialization的回调方法的调用
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// 调用Bean的初始化方法,这个初始化方法是在BeanDefinition中通过定义init-method
// 属性指定的,同时,如果Bean实现了InitiallizingBean接口,那么这个Bean的afterPropertiesSet实现也会被调用
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
// 这里是对后置处理器BeanPostProcessor的PostProcessAfterInitialization的回调方法调用
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
从以上代码实现中可以看到这两个Bean后置处理器定义的接口方法,一前一后,围绕着Bean定义的init-method方法调用,与IoC容器对Bean的管理有机结合起来了。
autowiring (自动依赖装配)的实现
在之前对IoC容器实现原理的分析中,一直是通过BeanDefinition的属性值和构造函数以显示的方式对Bean的依赖关系进行管理的。在spring中,相对这种显式的依赖管理方式,IoC容器还提供了自动依赖装配的方式,在这个过程中,不需要对Bean属性做显式的依赖关系声明,只需要配置好autowiring属性。IoC容器会根据这个属性的配置,使用反射自动查找属性的类型或名字,然后基于属性的类型或名字来自动匹配IoC容器中的Bean,从而自动完成依赖注入。
autowiring属性在对Bean属性进行依赖注入时起作用,对Bean属性依赖注入的实现原理,而从完成对Bean属性的自动依赖装配,是在populateBean中实现的。
populateBean的实现中,在处理一般的Bean之前,先对autowiring属性进行处理。如果当前的Bean配置了autowire_by_name和autowire_by_type属性。
首先通过反射机制从当前Bean中得到需要注入的属性名,然后使用这个属性名向容器申请与之同名的Bean,实际又触发了另一个Bean的生成和依赖注入的过程。
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
// 开始依赖注入的过程,先处理autowire注入
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据Bean的名字或类型完成Bean的autowire
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
通过调用autowireByName和autowireByType来完成自动依赖装配;
对autowireByName来说,首先需要得到当前Bean的属性名,这些属性名已经在BeanWrapper和BeanDefinition中封装好了,然后是对这一系列属性名进行匹配的过程。在匹配的过程中,因为已经有了属性的名字,所以可以直接使用属性名作为Bean名字向容器索取Bean,这个getBean会触发当前Bean的依赖Bean的依赖注入,从而得到属性对应的依赖Bean。在执行完这个getBean后,把这个依赖Bean注入到当前Bean的属性中取去,这样就完成了通过这个以来属性名完成依赖注入的过程。
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
// 使用取得的当前Bean的属性名作为Bean的名字,向IoC容器索取Bean,
// 然后把从容器得到的Bean设置到当前Bean的属性中去
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
Bean的依赖检查
在一般情况下,Bean的依赖注入是在应用第一次向容器索要Bean的时候发生的,在这个时候,不能保证注入一定能成功,如果需要重新检查这些依赖关系的有效性,会是一件很繁琐的事情。
为了解决这样的问题,在spring IoC容器中,设计了一个依赖检查特性,通过它,spring可以帮助应用检查是否所有的属性都被正确设置。
在具体使用的时候,应用只需要在Bean定义中设置dependency-check
属性来指定一来检查模式即可。模式包括:none、simple、object、all四种模式,默认为none。
具体的实现代码是在AbstractAutowireCapableBeanFactory
实现createBean的过程中完成的。这个过程会对Bean的Dependencies属性进行检查,如果发现不满足要求,就会抛出异常通知应用。
protected void checkDependencies(
String beanName, AbstractBeanDefinition mbd, PropertyDescriptor[] pds, @Nullable PropertyValues pvs)
throws UnsatisfiedDependencyException {
int dependencyCheck = mbd.getDependencyCheck();
for (PropertyDescriptor pd : pds) {
if (pd.getWriteMethod() != null && (pvs == null || !pvs.contains(pd.getName()))) {
boolean isSimple = BeanUtils.isSimpleProperty(pd.getPropertyType());
boolean unsatisfied = (dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_ALL) ||
(isSimple && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_SIMPLE) ||
(!isSimple && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
if (unsatisfied) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, pd.getName(),
"Set this property value or disable dependency checking for this bean.");
}
}
}
}
Bean对IoC容器的感知
容器管理的Bean一般不需要了解容器的状态和直接使用容器,但在某些情况下,需要在Bean中直接对IoC容器进行操作的,这时候,就需要在Bean中设定对容器的感知,springIoC容器也提供了该功能,它是通过特定的aware接口来完成的,aware接口有这些:
- BeanNameAware:可以在Bean中得到它在IoC容器的Bean实例名称。
- BeanFactoryAware:可以在Bean中得到Bean所在的IoC容器,从而直接在Bean中使用IoC容器服务。
- ApplicationContextAware:可以在Bean中得到Bean所在的应用上下文,从而直接在Bean中使用应用上下文服务。
- MessageSourceAware:在Bean中可以得到消息源。
- ApplicationEventPublisherAware:在Bean中可以得到应用上下文的事件发布器,从而可以在Bean中发布应用上下文事件。
- ResourceLoaderAware:在Bean中可以得到ResourceLoader,从而在Bean中使用ResourceLoader加载外部对应的Resource资源。