Spring源码阅读之bean对象的创建过程

​ Spring是通过IOC容器来管理对象的,该容器不仅仅只是帮我们创建了对象那么简单,它负责了对象的整个生命周期-创建、装配、销毁。这种方式成为控制反转(组件对象控制权的转移,从程序代码本身转移到了外部容器,容器创建完对象后注入组件中)。

​ Spring的核心的是容器,不过这个容器并不是唯一的,框架本身就提供了很多个容器的实现,大概分为两种类型:

  1. BeanFactory:最简单的容器,只能提供基本的DI(依赖注入)功能。
  2. ApplicationContext(应用上下文):继承自BeanFactory,它能提供更多企业级的服务,例如解析配置文本信息等等,这也是ApplicationContext实例对象最常见的应用场景。

简单说说这两种方式的区别

  1. 原始的BeanFactory无法支持spring的许多插件,如AOP功能、Web应用
  2. ApplicationContext利用MessageSource进行国际化 并有着事件机制。
  3. ApplicationContext扩展了ResourceLoader(资源加载器)接口,从而可以用来加载多个Resource,而BeanFactory是没有扩展ResourceLoader
  4. 与BeanFactory通常以编程的方式被创建不同的是,ApplicationContext能以声明的方式创建,如使用ContextLoader。当然你也可以使用ApplicationContext的实现之一来以编程的方式创建ApplicationContext实例 。
  5. BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样,我们就不能发现一些存在的spring的配置问题。而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误。

ApplicationContext 介绍

​ 如果说BeanFactory是Sping的心脏,那么ApplicationContext就是完整的身躯了。ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用的功能。在Beanfactory中,很多功能需要以编程的方式实现,而在ApplicationContext中则可以通过配置的方式实现。

ApplicationContext类体系结构:

在上一篇源码阅读WebContextApplication初始化中说到实际创建的对象为XmlWebApplicationContext,该类继承了AbstractRefreshableWebApplicationContext(上图的左下角),也是ApplicationContext体系。那么该对象读取配置文件后是如何创建bean对象的呢?

大致分为两步:

  1. 实例化BeanDefinition对象(下面分析该对象的作用) 。

  2. 实例化bean对象。

1. 实例化BeanDefinition对象

WebContextApplication初始化说到初始化的步骤是在ContextLoader中完成,创建完XmlWebApplicationContext对象后,通过configureAndRefreshWebApplicationContext()设置配置文件的位置。

protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {String configLocationParam;if (ObjectUtils.identityToString(wac).equals(wac.getId())) {configLocationParam = sc.getInitParameter("contextId");if (configLocationParam != null) {wac.setId(configLocationParam);} else {wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath()));}}//设置ServletContext环境。wac.setServletContext(sc);/*读取Servlet对象中的contextConfigLocation.  ServletContext在创建的时候就读取了<context-param>标签,并将该标签中的配置文件的信息通过键值对的形式保存进来了。*/configLocationParam = sc.getInitParameter("contextConfigLocation");if (configLocationParam != null) {//保存配置文件信息的位置。wac.setConfigLocation(configLocationParam);}//刷新环境wac.refresh();}

​ 配置文件位置设置完成后就需要读取该文件的配置信息,并创建相应的bean对象,这一过程就是在refresh()中完成的。

​ 通过图中的继承关系往上寻找在AbstractApplicationContext中发现·refresh方法,

该方法进行一些初始化操作。

public void refresh() throws BeansException, IllegalStateException {synchronized(this.startupShutdownMonitor) {// 1.刷新前的预处理,包含设置启动时间、设置状态...this.prepareRefresh();//实现刷新BeanFactory,将配置文件解析为BeanDefinition并注册到BeanFactory,此时Bean还未被初始化ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();// BeanFactory的预准备工作this.prepareBeanFactory(beanFactory);try {this.postProcessBeanFactory(beanFactory);// 执行BeanFactoryPostProcessor的方法,BeanFactory的后置处理器 // 在BeanFactory标准初始化之后执行的this.invokeBeanFactoryPostProcessors(beanFactory);// 注册BeanPostProcessor(Bean的后置处理器),用于拦截bean创建过程this.registerBeanPostProcessors(beanFactory);// 初始化MessageSource组件(做国际化功能;消息绑定,消息解析).this.initMessageSource();// 初始化上下文的事件机制this.initApplicationEventMulticaster();// 可以用于子类实现在容器刷新时自定义逻辑初始化this.onRefresh();// 注册时间监听器,将ApplicationListener注册到容器中来this.registerListeners();// 初始化所有剩下的单实例bean,单例bean在初始化容器时创建。this.finishBeanFactoryInitialization(beanFactory);// 发布完成事件,结束初始化过程this.finishRefresh();} catch (BeansException var5) {this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var5);this.destroyBeans();this.cancelRefresh(var5);throw var5;}}}

obtainFreshBeanFactory将配置文件解析为BeanDefinition并注册到BeanFactory中

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {// 主要是通过该方法完成IoC容器的刷新this.refreshBeanFactory();ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();if (this.logger.isDebugEnabled()) {this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory);}return beanFactory;}

refreshBeanFactory完成IOC容器的刷新,具体实现是在AbstractRefreshableApplicationContext中,实际创建的的IOC容器为:DefaultListableBeanFactory

protected final void refreshBeanFactory() throws BeansException {//首先检查是否已经有beanFactory了,有就销毁if (this.hasBeanFactory()) {this.destroyBeans();this.closeBeanFactory();}try {// 创建IoC容器,也就是DefaultListableBeanFactoryDefaultListableBeanFactory beanFactory = this.createBeanFactory();beanFactory.setSerializationId(this.getId());this.customizeBeanFactory(beanFactory);//载入刚创建的IOC容器,具体实现在子类XmlWebApplicationCpntext中this.loadBeanDefinitions(beanFactory);synchronized(this.beanFactoryMonitor) {this.beanFactory = beanFactory;}} catch (IOException var5) {throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);}}

loadBeanDefinitions装载刚创建的IOC容器,具体实现在XmlWebApplicationCpntext中。

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {// 创建一个BeanDefinition阅读器,通过阅读XML文件,真正完成BeanDefinition的加载和注册XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);//beanDefinitionReaderde 初始化操作beanDefinitionReader.setEnvironment(this.getEnvironment());beanDefinitionReader.setResourceLoader(this);beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));this.initBeanDefinitionReader(beanDefinitionReader);this.loadBeanDefinitions(beanDefinitionReader);}
//方法重载
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {/*在上一篇文章中ContextLoader中的configureAndRefreshWebApplicationContext方法有这一段代码configLocationParam = sc.getInitParameter("contextConfigLocation");if (configLocationParam != null) {//保存配置文件信息的位置。wac.setConfigLocation(configLocationParam);}这里就是读取配置文件的信息,保存进数组中。*/String[] configLocations = this.getConfigLocations();if (configLocations != null) {String[] var3 = configLocations;int var4 = configLocations.length;for(int var5 = 0; var5 < var4; ++var5) {String configLocation = var3[var5];//具体的装载方法在XmlBeanDefinitionReaderreader.loadBeanDefinitions(configLocation);}}}

​ 接下来看XmlBeanDefinitionReader中的loadBeanDefinitions()

public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {// 对配置文件进行编码处理return this.loadBeanDefinitions(new EncodedResource(resource));
}
//截取主要代码
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {try {//将配置文件转换成流对象InputStream inputStream = encodedResource.getResource().getInputStream();try {// 从InputStream中得到XML的解析源InputSource inputSource = new InputSource(inputStream);if (encodedResource.getEncoding() != null) {inputSource.setEncoding(encodedResource.getEncoding());}// 这里是具体的读取过程,var5等于新注册的BeanDefintion数量var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());} finally {inputStream.close();}}

​ 具体的读取过程在doLoadBeanDefinitions()中,该方法的主要作用就是:

  • 一个是对XML文件进行DOM解析
  • 一个是完成BeanDefinition对象的加载与注册
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {try {//把资源文件转换成Document对象Document doc = this.doLoadDocument(inputSource, resource);// 通过对Document对象的操作,完成BeanDefinition的加载和注册工作return this.registerBeanDefinitions(doc, resource);}Catch(){}}

​ 看看registerBeanDefinitions()具体完成了哪些操作:

  1. 创建DefaultBeanDefinitionDocumentReader用来解析Document对象。
  2. 获得容器中已注册的BeanDefinition数量
  3. 委托给DefaultBeanDefinitionDocumentReader来完成BeanDefinition的加载、注册工作。
  4. 统计新注册的BeanDefinition数量
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {//  1.BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();documentReader.setEnvironment(this.getEnvironment());// 2.int countBefore = this.getRegistry().getBeanDefinitionCount();// 3. 解析过程入口,BeanDefinitionDocumentReader只是个接口,具体的实现过程在DefaultBeanDefinitionDocumentReader完成documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));// 4.return this.getRegistry().getBeanDefinitionCount() - countBefore;}

​ 接着看DefaultBeanDefinitionDocumentReader中的registerBeanDefinitions()该方法:

  • 获得Document的根元素标签
  • 真正实现BeanDefinition解析和注册工作
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {this.readerContext = readerContext;this.logger.debug("Loading bean definitions");//获取文档对象的子节点。Element root = doc.getDocumentElement();//真正的解析注册方法this.doRegisterBeanDefinitions(root);}

​ 到这一步接下来就是对解析文档中的每一个标签节点,获取标签中的属性。创建AbstractBeanDefinition对象,并将标签中属性保存进对象中。具体的步骤就不展示了。

​ 综上步骤具体完成了以下操作:

  1. 创建IoC容器(DefaultListableBeanFactory)

  2. 加载解析XML文件(最终存储到Document对象中)

  3. 读取Document对象,并完成BeanDefinition的加载和注册工作

    BeanDefinition 在 spring 中贯穿始终,spring 要根据 BeanDefinition 对象来实

例化 bean,只有把解析的标签,扫描的注解类封装成 BeanDefinition 对象,spring

**才能实例化 bean **

​ 上面的步骤只是完成了AbstractApplicationContext中refresh()这句话(心累…)

ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();

2. 实例化Bean对象

​ 进入AbstractApplicationContext中的finishBeanFactoryInitialization()

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {beanFactory.setTempClassLoader((ClassLoader)null);beanFactory.freezeConfiguration();// 实例化剩余的单例bean(非懒加载方式)// 注意事项:Bean的IoC、DI和AOP都是发生在此步骤beanFactory.preInstantiateSingletons();}

进入DefaultListableBeanFactory中的preInstantiateSingletons()方法:

  • 通过beanName获取bean实例,如果获取到的实例不满足条件就看最后一行getBean(beanName);
  • 核心代码 getBean(beanName);
@Overridepublic void preInstantiateSingletons() throws BeansException {if (this.logger.isDebugEnabled()) {this.logger.debug("Pre-instantiating singletons in " + this);}// 得到Bean定义名称List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// 触发所有非懒加载方式的单例bean的创建for (String beanName : beanNames) {// 遍历得到对应的bean定义信息RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);// 如果bean不是抽象的,而且是单例的,同时还不是懒加载的,则进行下面的操作if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {// 如果bean是一个工厂bean,则走下面的方法 ,和普通bean区别就是还可以生成beanif (isFactoryBean(beanName)) {Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {final 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 { // 普通bean走下面的方法getBean(beanName);}}}

​ 进入AbstractBeanFactory通过doGetBean()方法获取Bean的实例(只展示关键代码)

  1. 通过getSingleton(beanName)方法去缓存中获取单例Bean(第一次初始化,缓存中不存在)

  2. 如果取出来的bean实例是factoryBean的实例,则需要从factoryBean中产生一个Bean对象

  3. 根据当前的beanfactory获取父一级的beanFactory,递归查找我们需要的Bean(Bean是早不到的,第一次初始化)

  4. 获取实例化Bean的BeanDefinition对象

  5. 一般是单例Bean,用匿名内部类的写法,创建单例Bean

    @Overridepublic Object getBean(String name) throws BeansException {// 获取Bean的实例return doGetBean(name, null, null, false);}@SuppressWarnings("unchecked")protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {// 获取bean名称final String beanName = transformedBeanName(name);Object bean;// Eagerly check singleton cache for manually registered singletons.// 从缓存中获取单例beanObject sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) { //如果获取到单例bean,则走下面代码if (logger.isDebugEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.debug("Returning cached instance of singleton bean '" + beanName + "'");}}// 如果取出来的Bean实例是FactoryBean的Bean实例,则需要从FactoryBean实例中产生一个对象实例。bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {//如果没有获取到单例bean,则走下面代码try {// 获取要实例化的bean的BeanDefinition对象final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// 检查该BeanDefinition对象对应的Bean是否是抽象的checkMergedBeanDefinition(mbd, beanName, args);// 如果是单例的Bean,请下面的代码if (mbd.isSingleton()) {                    //匿名内部类的写法sharedInstance = getSingleton(beanName, () -> {try {// 创建单例Bean的主要方法return createBean(beanName, mbd, args);}catch (BeansException ex) {destroySingleton(beanName);throw ex;}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}return (T) bean;
    }
    

    进一步看看createBean()具体实现在AbstractAutowireCapableBeanFactory

    @Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {//省略一些代码try {// 完成Bean实例的创建(实例化、填充属性、初始化)Object beanInstance = doCreateBean(beanName, mbdToUse, args);if (logger.isDebugEnabled()) {logger.debug("Finished creating instance of bean '" + beanName + "'");}return beanInstance;}
    ****

    doCreateBean完成Bean实例的创建(实例化、填充属性、初始化)

    • bean初始化第一步,默认调用无参数构造实例化bean
    • bean初始化第二步,填充属性(DI依赖注入发生在此步骤)
    • bean初始化第三步,调用初始化方法,完成bean的初始化操作AOP发生在此步骤)
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.// 用BeanWrapper来持有创建出来的Bean对象BeanWrapper instanceWrapper = null;// 如果是单例的话,则先把缓存中的bean清除if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}// bean初始化第一步:默认调用无参构造实例化Bean// 构造参数依赖注入,就是发生在这一步// 为了下一步populateBean方法的属性注入做准备if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}// 实例化后的Bean对象final 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));// 如果需要提前暴露单例Bean,则将该Bean放入三级缓存中if (earlySingletonExposure) {if (logger.isDebugEnabled()) {logger.debug("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}// 将刚创建的bean放入三级缓存中singleFactories(key是beanName,value是FactoryBean)addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}// Initialize the bean instance.Object exposedObject = bean;try {// bean初始化第二步:填充属性(DI依赖注入发生在此步骤)populateBean(beanName, mbd, instanceWrapper);// bean初始化第三步:调用初始化方法,完成bean的初始化操作(AOP发生在此步骤)exposedObject = initializeBean(beanName, exposedObject, mbd);}
    ******************************************
    }
    

    进入上面的initializeBean()方法:

    • 应用BeanPostProcessor的postProcessBeforeInitialization方法在初始化之前被调用
    • 执行初始化方法(先调用InitializingBean的afterPropertiesSet,再调用init-method属性指定的初始化方法,最后BeanPostProcessor的postProcessAfterInitialization)
    • 应用BeanPostProcessor的postProcessAfterInitialization方法(AOP代理对象生成)在初始化之后被调用
    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 {/*判断beanName是哪个接口的的实现类如果bean是BeanNameAware接口的实现类会调用setBeanName方法、如果bean是BeanClassLoaderAware接口的实现类会调用setBeanClassLoader方法、如果是BeanFactoryAware接口的实现类会调用setBeanFactory方法,注入对应的属性值。*/invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {//应用BeanPostProcessor的postProcessBeforeInitialization方法wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {//执行初始化方法(先调用InitializingBean的afterPropertiesSet,再调用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的postProcessAfterInitialization方法(AOP代理对象生成)// AOP是等着对象创建完毕,在进行增强wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}
    

    调用初始化方法invokeInitMethods()

    • 判断是否是InitializingBean接口的实现类,如果是县初始化InitializingBean
    • 如果不是则调用InitializingBean接口中的afterPropertiesSet方法
    • 然后再初始化标签对应的init-method属性中的方法
    protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)throws Throwable {boolean isInitializingBean = (bean instanceof InitializingBean);// 如果是InitializingBean接口的实现类,则先初始化InitializingBean的实现类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 {// 调用InitializingBean接口的afterPropertiesSet方法((InitializingBean) bean).afterPropertiesSet();}}// 然后再初始化<bean>标签对应的init-method属性中的方法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);}}}
    

    在initializeBean方法中调用BeanPostProcessor的applyBeanPostProcessorsAfterInitialization方法

    • 在初始化Bean的时候都会调用每一个配置的BeanPostProcessor的方法
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {Object result = existingBean;Iterator var4 = this.getBeanPostProcessors().iterator();do {if (!var4.hasNext()) {return result;}BeanPostProcessor beanProcessor = (BeanPostProcessor)var4.next();//bean初始化后调用result = beanProcessor.postProcessAfterInitialization(result, beanName);} while(result != null);return result;}
    

    BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口。接口声明如下:

    public interface BeanPostProcessor {//bean初始化方法调用前被调用Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;//bean初始化方法调用后被调用Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
    }

    至此bean的初始化就完成了。

tProcessor)var4.next();
//bean初始化后调用
result = beanProcessor.postProcessAfterInitialization(result, beanName);
} while(result != null);

       return result;}

BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口。接口声明如下:```java
public interface BeanPostProcessor {//bean初始化方法调用前被调用Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;//bean初始化方法调用后被调用Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

至此bean的初始化就完成了。
参考:https://www.jianshu.com/p/32dacf644062 作者:GGarrett

Spring源码阅读之bean对象的创建过程相关推荐

  1. Spring源码解析-实例化bean对象

    spring加载配置文件,AbstractApplicationContext类中的refresh方法起着重要的作用. @Overridepublic void refresh() throws Be ...

  2. Spring源码解析:自定义标签的解析过程

    2019独角兽企业重金招聘Python工程师标准>>> spring version : 4.3.x Spring 中的标签分为默认标签和自定义标签两类,上一篇我们探究了默认标签的解 ...

  3. JVM源码简析(楔子)-对象内存分配过程和PS回收器中YGC触发FGC的现象

    前言 想要搞明白Java对象内存申请过程的原因,是因为第一次接触线上GC日志的时候,发现了一些很奇怪的现象,就是young gc触发了full gc.为了搞清楚这个现象,得先要来个测试去复现. 复现现 ...

  4. Spring源码阅读(一)——整体结构

    Spring 总共大约有20个模块,由1300多个不同的文件构成. Spring源码阅读可以分为三个路线:IOC,AOP,外部组件. 个人主页:tuzhenyu's page 原文地址:Spring源 ...

  5. spring源码阅读(3)-- 容器启动之BeanFactoryPostProcessor

    接着上文<spring源码阅读(2)-- 容器启动之加载BeanDefinition>,当spring加载完所有BeanDefinition时,并不会马上去创建bean,而是先配置bean ...

  6. 【Spring 源码阅读】Spring IoC、AOP 原理小总结

    Spring IoC.AOP 原理小总结 前言 版本约定 正文 Spring BeanFactory 容器初始化过程 IoC 的过程 bean 完整的创建流程如下 AOP 的过程 Annotation ...

  7. Spring源码分析之Bean的创建过程详解

    前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...

  8. Spring源码分析系列——bean创建过程分析(三)——工厂方法创建bean

    前言 spring创建bean的方式 测试代码准备 createBeanInstance()方法分析 instantiateUsingFactoryMethod()方法分析 总结 spring创建be ...

  9. 我该如何学习spring源码以及解析bean定义的注册

    如何学习spring源码 前言 本文属于spring源码解析的系列文章之一,文章主要是介绍如何学习spring的源码,希望能够最大限度的帮助到有需要的人.文章总体难度不大,但比较繁重,学习时一定要耐住 ...

最新文章

  1. GDCM:读取显式长度SQIVR的测试程序
  2. android圆形变方形动画,CSS3 简单的圆形/方形变形动画
  3. CSS布局技巧之——各种居中
  4. php打印出函数的内容吗,PHP打印函数集合详解以及PHP打印函数对比详解(精)
  5. 谷歌大改Transformer注意力,速度大涨,显存大降!
  6. PHP结合Redis来限制用户或者IP某个时间段内访问的次数
  7. Adversarial examples in the physical world论文解读
  8. 异常、模块、文件读写
  9. java arraydeque poll,Java ArrayDeque pollLast()方法
  10. Atitit alldiaryindex v1 t717 目录 1. Fix 1 2. Diary detail 1 2.1. Diary 1987---2016.12 1 2.2. Diary20
  11. 【数字信号处理】基于Matlab GUI数字均衡器设计【含Matlab源码 904期】
  12. 80x86段寻址的原因
  13. 泪目!java面试八股文是哪些
  14. 百度“有啊”困局之源:流量到交易的转化
  15. 计算机桌面图标变大,电脑桌面图标变大了怎么恢复?
  16. FireFoxOS 初体验
  17. heic格式怎么改成jpg?
  18. Redhat Enterprise Linux 6.5下安装Oracle11g R2
  19. 120M硬盘的jslinux
  20. 手把手教你升级Keil MDK的ARM编译器

热门文章

  1. 好的广告片拍摄制作公司都具备哪些能力?
  2. 嗨,华为,我想找个“懂行”的人
  3. FME写入Excel数据时写到模板文件指定位置
  4. php触屏签字,触摸屏签名软件
  5. BigInteger使用
  6. 5.4结构型模式—————装饰模式
  7. 黄健翔质疑半自动越位技术?用「技术流」解读卡塔尔世界杯
  8. SuperMap申请试用许可
  9. 访客模式 无痕模式 区别_访客设计模式
  10. 根据Geohash编码画中心点和边框