本文是笔者所著的 Spring Core Container 源码分析系列之一;java
本篇文章主要试图梳理出 Spring Beans 的初始化主流程
和相关核心代码逻辑;spring
本文转载自本人的私人博客,伤神的博客: http://www.shangyang.me/2017/...缓存
本文为做者的原创做品,转载需注明出处;架构
参考 Spring Core Container 源码分析二:环境准备app
依然使用这个官网上的用例,来进行调试;ide
Person.java函数
package org.shangyang.spring.container; /** - - @author shangyang * */ public class Person { String name; Person spouse; public String getName() { return name; } public void setName(String name) { this.name = name; } public Person getSpouse() { return spouse; } public void setSpouse(Person spouse) { this.spouse = spouse; } }
beans.xml源码分析
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 传统的方式 --> <bean name="john" class="org.shangyang.spring.container.Person"> <property name="name" value="John Doe"/> <property name="spouse" ref="jane"/> </bean> <bean name="jane" class="org.shangyang.spring.container.Person"> <property name="name" value="Jane Doe"/> </bean> </beans>
@Test public void testApplicationContext(){ @SuppressWarnings("resource") ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Person p = context.getBean("john", Person.class); assertEquals("John Doe", p.getName() ); assertEquals("Jane Doe", p.getSpouse().getName() ); }
备注,这里只针对 Spring 容器实例化 singleton bean 的主流程进行介绍;_singleton_ bean 在 Spring 容器中被初始化的特色是,在 Spring 容器的启动过程当中就进行初始化;post
(最好的分析源码的方式,就是经过高屋建瓴,逐个击破的方式;首先经过流程图得到它的蓝图(顶层设计图),而后再根据蓝图上的点逐个击破;最后才能达到融会贯通,成竹在胸的境界;因此,这里做者用这样的方式带你深刻剖析 Spring 容器里面的核心点,以及相关主流程究竟是如何运做的。)测试
本章节咱们将详细去阐述的是,Spring 容器是如何对 Singleton bean 进行初始化并注册到当前容器的;与之相关的主要有两个流程,
AbstractBeanFactory#getBean(beanFactory)
方法进行构造;更详细的介绍参考 Do Get Bean 流程。该部分参考新的博文 Spring Core Container 源码分析七:注册 Bean Definitions
Do Get Bean 流程的入口是 AbstractBeanFactory#doGetBean 方法,主流程图以下,
主流程大体为,从缓存中找到是否已经实例化了该 singleton bean,若是已经实例化好了,那么就直接返回;若是在缓存中没有找到,则将当前的 bean 封装为 RootBeanDefinition,而后经过调用 DefaultSingletonBeanRegistry#getSingleton 获得初始化好的 singleton bean,而后将其注册至缓存( step 1.3.3 addSingleton ),而后再判断是普通 bean 仍是 factory bean 做必要的处理( step 1.4 getObjectForBeanInstance )后,最后返回;
初始化了一个 RootBeanDefinition
对象,正如其类名描述的那样,是该 bean 的顶层描述;包含了 bean 的字段属性,ref属性以及继承相关等等属性;
此步骤的相关代码以下,
// Create bean instance. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { 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); }
调用父类 DefaultSingletonBeanRegistry#getSingleton 方法;注意,这里经过接口 ObjectFactory<Object>
定义了一个回调方法 _getObject()_,经过该回调方法调用 AbstractAutowireCapableBeanFactory#createBean 方法,经过此回调方法正式拉开了实例化 bean 的序幕
。
AbstractAutowireCapableBeanFactory#doCreateBean 方法是初始化 bean 的最核心的入口方法,执行流程如 Do Get Bean 流程所示,
下面咱们分别来分析这三件事情
该步骤对应 Do Get Bean 流程中的 _Step 1.3.1.1.3.1 createBeanInstance_;根据 bean 的不一样配置方式,实现了三种实例化 bean 的方式,分别是 factory instantiate bean、autwire instantiate bean 以及 default instantiate bean;
用工厂方法实例化 bean,待叙;
经过 autowire 注解的方式实例化 bean,待叙;
此步骤对应 Do Get Bean 流程中的 Step 1.3.1.1.3.1.3 instantiateBean_,其对应子流程 _default instantiate bean 以下图所示,
注意几点
Java 反射
实例化了 bean,并没有对其进行任何的参数赋值,赋值过程参考 populate bean 流程;将 bean 封装为 BeanWrapper,而后
最后返回 BeanWrapper
对应 Do Get Bean 流程中的 Step 1.3.1.1.3.4 populateBean_,经过调用 _AbstractAutowireCapableBeanFactory#populateBean 正式给 bean 的参数进行赋值;为何方法名取名为populate
呢?查百度翻译,结果是居住于、生活于、移民于、落户于的意思,丝毫没有赋值的意思,可是记得之前和美国人共事的时候,他们很是喜欢用这个词populate
,特别是在建立某个对象的时候,他们特别喜欢用这个词;后来无心中发现,populate
有建立
和填充
的意思,因此,这里的意思就是,填充
这个 bean;下面看看 populate bean 的流程图,看看它是怎么玩的,
经过调用 AbstractAutowireCapableBeanFactory#applyPropertyValues 方法正式给 bean 进行赋值操做,赋值的主流程主要包括两个部分,resolve property value object 和 set property value to bean
对应上面 Sequence Diagram 中的 Step 1.5 - Step 1.7_;这一步主要是去遍历当前 bean 全部的 property,并依次解析(resolve)获得对应的 Java 对象;经过方法 _BeanDefinitionValueResolver#resolveValueIfNecessary 进行解析,解析的过程是针对不一样类型的 Property,采用不一样的解析方式,里面目前总共对应了十种类型,先看看它的源码,
public Object resolveValueIfNecessary(Object argName, Object value) { // We must check each value to see whether it requires a runtime reference // to another bean to be resolved. if (value instanceof RuntimeBeanReference) { // 这里表示该 bean definition ref 引用的是一个 bean,那么这里,必须对该 bean 进行初始化操做; RuntimeBeanReference ref = (RuntimeBeanReference) value; return resolveReference(argName, ref); } else if (value instanceof RuntimeBeanNameReference) { String refName = ((RuntimeBeanNameReference) value).getBeanName(); refName = String.valueOf(doEvaluate(refName)); if (!this.beanFactory.containsBean(refName)) { throw new BeanDefinitionStoreException( "Invalid bean name '" + refName + "' in bean reference for " + argName); } return refName; } else if (value instanceof BeanDefinitionHolder) { // Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases. BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value; return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition()); } else if (value instanceof BeanDefinition) { // Resolve plain BeanDefinition, without contained name: use dummy name. BeanDefinition bd = (BeanDefinition) value; String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(bd); return resolveInnerBean(argName, innerBeanName, bd); } else if (value instanceof ManagedArray) { // May need to resolve contained runtime references. ManagedArray array = (ManagedArray) value; Class<?> elementType = array.resolvedElementType; if (elementType == null) { String elementTypeName = array.getElementTypeName(); if (StringUtils.hasText(elementTypeName)) { try { elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader()); array.resolvedElementType = elementType; } catch (Throwable ex) { // Improve the message by showing the context. throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Error resolving array type for " + argName, ex); } } else { elementType = Object.class; } } return resolveManagedArray(argName, (List<?>) value, elementType); } else if (value instanceof ManagedList) { // May need to resolve contained runtime references. return resolveManagedList(argName, (List<?>) value); } else if (value instanceof ManagedSet) { // May need to resolve contained runtime references. return resolveManagedSet(argName, (Set<?>) value); } else if (value instanceof ManagedMap) { // May need to resolve contained runtime references. return resolveManagedMap(argName, (Map<?, ?>) value); } else if (value instanceof ManagedProperties) { Properties original = (Properties) value; Properties copy = new Properties(); for (Map.Entry<Object, Object> propEntry : original.entrySet()) { Object propKey = propEntry.getKey(); Object propValue = propEntry.getValue(); if (propKey instanceof TypedStringValue) { propKey = evaluate((TypedStringValue) propKey); } if (propValue instanceof TypedStringValue) { propValue = evaluate((TypedStringValue) propValue); } copy.put(propKey, propValue); } return copy; } else if (value instanceof TypedStringValue) { // Convert value to target type here. TypedStringValue typedStringValue = (TypedStringValue) value; Object valueObject = evaluate(typedStringValue); try { Class<?> resolvedTargetType = resolveTargetType(typedStringValue); if (resolvedTargetType != null) { return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType); } else { return valueObject; } } catch (Throwable ex) { // Improve the message by showing the context. throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Error converting typed String value for " + argName, ex); } } else { return evaluate(value); } }
这里主要关注两类解析,
对应须要被解析的配置为john
的 property spouse
,它所对应的值是另外一个 bean jane
;既是一个去解析一个ref bean
。
<property name="spouse" ref="jane"/>
因此能够看到,源码中是经过 resolveReference 方法调用 AbstractBeanFactory#getBean 方法去实例化
一个 bean jane
并返回;对应的源码以下,
BeanDefinitionValueResolver#resolveReference
/** * Resolve a reference to another bean in the factory. */ private Object resolveReference(Object argName, RuntimeBeanReference ref) { try { String refName = ref.getBeanName(); refName = String.valueOf(doEvaluate(refName)); if (ref.isToParent()) { if (this.beanFactory.getParentBeanFactory() == null) { throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Can't resolve reference to bean '" + refName + "' in parent factory: no parent factory available"); } return this.beanFactory.getParentBeanFactory().getBean(refName); } else { Object bean = this.beanFactory.getBean(refName); // 去获得这个 ref bean this.beanFactory.registerDependentBean(refName, this.beanName); // 注册 return bean; } } catch (BeansException ex) { throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex); } }
经过调用this.beanFactory.getBean(refName)
再次进入Do Get Bean 流程初始化获得该 _ref bean_;
最后,将解析出来的 Property value 放在一个deepCopy
的 ArrayList 列表对象中;顾名思义,就是对值进行了一次深度的拷贝,而后将其做为 bean 的参数,随后开始进行赋值操做);
这里主要被解析的 Property value 的类型配置为
<property name="name" value="John Doe"/>
其 Property value 的值在配置文件中就是一个纯的字符串类型;但从源码中能够知道,Property value 是能够包含 value type 的,因此,在解析 TypedStringValue 的时候,须要根据 value type 进行解析;具体逻辑参考resolveTargetType(typedStringValue);
方法。
此步骤的主流程主要是经过Java Method 反射
将解析出来的值赋值给当前的 bean;对应时序图中的 Step 1.8 setPropertyValues
能够看到,经过遍历 deepCopy
ArrayList 对象中已经解析事后的 PropertyValue,最终由 BeanWrapperImpl 对象经过方法的反射,将值注入给当前的 bean,_Step 1.8.1.2.1.2.2 writeMethod.invoke_
BeanWrapperImpl.java 省略了大部分可有可无的代码,
@Override public void setValue(final Object object, Object valueToApply) throws Exception{ final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ? ((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() : this.pd.getWriteMethod()); if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { writeMethod.setAccessible(true); return null; } }); } else { writeMethod.setAccessible(true); } } .... writeMethod.invoke(getWrappedInstance(), valueToApply); .... }
经过这一步,将相关的 property populate 给 bean 之后,才算 bean 的实例化完成;
正如流程图中所描述的那样,这个步骤的名字很是然人迷惑,我将流程图中写的备注摘录以下,
"注意, 这里的名称很容易让人产生混淆, 很容易让人产生这样一个疑问, 前面不是已经初始化好了, bean 建立好了, bean 相关的 property 也设置好了, 怎么这里还要进行初始化? 这里其实偏偏充分体现了西方人写代码的严谨, 前面的部分叫作 instantiation, 叫作"实例化", 而这里叫作 initialization, 叫作 "初始化"; 这样一说, 差很少就明白了, "实例化"就是从 class 获得 instance 的过程; 而"初始化", 包含的意义更普遍, 其意义包含了"实例化"和其它对 instance 的修饰的过程, 而这里, 其实就是对已经建立好的 bean instance 进行"修饰"的过程。"
因此,这里的 initialize 其实就是对经过 instantiate bean 和 populate bean 两个步骤实例化好的 bean 进行后续必要的修饰;咱们经过流程图来看看,它是怎么去修饰的,
经过 AbstractAutowireCapableBeanFactory#initializeBean 方法进行对 bean 的修饰过程,看源码,(删除了大部分不相关的代码)
AbstractAutowireCapableBeanFactory.java
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { invokeAwareMethods(beanName, bean); // 调用实现了 *Aware 接口的方法,好比注入 ApplicationContext... Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // 调用 bean-post-processor 的 before initialization 回调方法 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); // 调用 InitializingBean#afterPropertiesSet 回调 } 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 的 after initialization 回调方法 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; // 这里的 wrapped bean 指的是被 bean-post-processor 修饰之后的包装 bean }
整个过程能够理解为三大块,
下面,咱们依次来梳理这三个部分;
对应流程图中的 _Step 1.1 invokeAwareMethods_,该步骤注册全部实现了Aware
接口的 beans
Aware.java
/** * Marker superinterface indicating that a bean is eligible to be * notified by the Spring container of a particular framework object * through a callback-style method. Actual method signature is * determined by individual subinterfaces, but should typically * consist of just one void-returning method that accepts a single * argument. * * <p>Note that merely implementing {@link Aware} provides no default * functionality. Rather, processing must be done explicitly, for example * in a {@link org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessor}. * Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor} * and {@link org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory} * for examples of processing {@code *Aware} interface callbacks. * * @author Chris Beams * @since 3.1 */ public interface Aware { }
从 Aware 接口的注释中能够看到,容许实现了该 Aware 接口的当前 bean 可以有机会经过回调的方式注入 Spring 容器中默认实现了 Aware 接口的 bean,好比 BeanFactory 等;看看源码,
AbstractAutowireCapableBeanFactory.java
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) { ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader()); } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } }
能够看到,注入了三种状况,
当梳理完这个部分之后,我相信读者会和我同样有这样的疑问,咱们不是常常经过Aware
的方式注入ApplicaitonContext
对象的吗?但和明显,上述的代码并无注入ApplicationContext
对象呀?看以下部分分析,
下列部分是延生部分
可是要特别特别注意的是,这里并没有注入ApplicationContext
对象,要注入ApplicaitonContext
对象,bean 必须实现ApplicatonContextAware
接口;
ApplicationContextAware.java
public interface ApplicationContextAware extends Aware { /** * Set the ApplicationContext that this object runs in. * Normally this call will be used to initialize the object. * <p>Invoked after population of normal bean properties but before an init callback such * as {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()} * or a custom init-method. Invoked after {@link ResourceLoaderAware#setResourceLoader}, * {@link ApplicationEventPublisherAware#setApplicationEventPublisher} and * {@link MessageSourceAware}, if applicable. * @param applicationContext the ApplicationContext object to be used by this object * @throws ApplicationContextException in case of context initialization errors * @throws BeansException if thrown by application context methods * @see org.springframework.beans.factory.BeanInitializationException */ void setApplicationContext(ApplicationContext applicationContext) throws BeansException; }
从注解中能够看到,它明确标注,是在 populate bean 之后,在 处理 InitializingBean 接口回调 以前调用,那是究竟是在什么时刻呢?咱们查看下方法 setApplicationContext 方法在 workspace 中的引用,它是在 ApplicationContextAwareProcessor#invokeAwareInterfaces 方法中被调用,而 ApplicationContextAwareProcessor 正好是一个 BeanPostProcessor 对象,因此,ApplicaitonContext
对象其实是在 bean-post-procesor before initialization流程中被注入的,看源码,
ApplicationContextAwareProcessor.java (省略了大部分不相关的代码)
class ApplicationContextAwareProcessor implements BeanPostProcessor { private final ConfigurableApplicationContext applicationContext; private final StringValueResolver embeddedValueResolver; /** * Create a new ApplicationContextAwareProcessor for the given context. */ public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) { this.applicationContext = applicationContext; this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory()); } @Override 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); } } } @Override public Object postProcessAfterInitialization(Object bean, String beanName) { return 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; }
该接口定义了两个回调方法,
因此,bean-post-processors 总共有两次调用的时机,分别是 before initialization 和 after initialization,并且要特别注意的是,该回调方法是针对对容器中全部的
普通 bean 进行的回调;
该步骤对应 Step 1.2 applyBeanPostProcessorsBeforeInitialization_,而后正式调用 _Step 1.2.1 beanPostProcessor.postProcessBeforeInitialization bean-post-processor 的回调方法,不过这里要注意的是,若是 Step 1.2.1 返回 null,会终止余下的 post-bean-processor 的执行,而且直接返回一个 null,该 null 一样被视为是封装后的产物,既然是 null,那么后续的 bean-post-processor 也无需处理了,也没法对原有的 bean 进行包装了.. 不过,我到以为这里的 Spring 源码的逻辑应该改进一下
,不容许返回 null 的状况,若是返回 null 则报错最好,由于 bean-post-processor 是对原有 bean 进行修饰,是新增属性,而非干掉实例自己.. 来看看源码,
AbstractAutowireCapableBeanFactory.java
@Override public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessBeforeInitialization(result, beanName); if (result == null) { return result; } } return result; }
若是某个 beanProcessor 处理返回一个 null 则直接返回,而且终止其他的 bean-post-processors
对应的是 step 1.4 applyBeanPostProcessorsAfterInitialization 步骤,里面的逻辑和 before initialization 逻辑相似,再也不赘述。
该步骤对应的是 _Step 1.3: invokeInitMethod_,回调 InitializingBean 接口方法,看源码,
AbstractAutowireCapableBeanFactory.java (删除了大部分不相关的代码)
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 起到修饰的做用,而是起到纯粹的调用做用;
以上即是 Spring IoC 容器的核心实现了,容器要达到的最本质的目的就是IoC
既反转控制
,由容器来负责管理对象实例相关依赖的初始化和注入,而再也不是由 bean 本身去控制本身的依赖的初始化和注入过程了;而IoC
的实现是经过DI
既是依赖注入实现的;也就是为何上面所介绍的内容都是围绕着 Spring 容器如何实例化一个 bean,如何赋值,如何进行回调等一系列在 bean 的构建声明周期过程当中的种种行为;
这样作能达到的好处就是,
(这里我忽然想到“微内核架构”,Java 的一种内置的依赖注入的方式,经过在 META-INF 中配置接口属性文件,里面其实就是配置的一个接口的实现类,经过它来控制接口在 JVM 中该接口所使用的实现类;但它只是控制某个接口如何在 JVM 中实现,将接口的实现翻转控制了,而 Spring 是对全部的 Class Instance 进行翻转控制,因此一个是站在局部上的反转控制设计,一个是站在全局上的反转控制设计,不可同日而语!)