Spring IOC容器初始化基础过程源码了解

本文详细剖析了Spring IOC初始化bean的基本过程,从AnnotationConfigApplicationContext构造方法开始,讲解了refresh()方法中的bean工厂创建、bean处理器的前后处理、单例非懒加载bean的初始化等步骤。通过源码分析,展示了从bean定义注册到bean实例化完成的完整流程,帮助读者深入理解Spring IOC的内部工作机制。
摘要由CSDN通过智能技术生成

Spring IOC初始化有很多种方式,如xml方式、注解方式(也分很多不同的方式)、FactoryBean方式等等,这个在之前的博客中有写过(Spring IOC初始化bean对象创建的N种实现方式理解)。这里就其中的一种方式来理解一下整个创建bean的基本过程。

前提说明

在写之前,先说明一下场景。

  • 这里是从AnnotationConfigApplicationContext的构造方法进入。当然进入的还有很多其他方式,如ClassPathXmlApplicationContext等。他们的共同点都是继承与ApplicationContext
  • 这里只做基本的说明,至于代理对象生成考虑、后置处理器的工作机制,多例的情况下如何运作,以后的博客会慢慢的来分析,这里解释的是单例非懒加载实例的初始化过程
  • 另外在贴出的源代码中,使用省略号将部分代码替代,否则代码过多反而影响对源代码的理解。

源码分析

在做IOC容器初始化的时候,采用下面的方式:

ApplicationContext app = new AnnotationConfigApplicationContext(InitDemo.class);

进入到上面AnnotationConfigApplicationContext(clazz)的构造方法中,源码如下:

/**
 * Create a new AnnotationConfigApplicationContext, deriving bean definitions
 * from the given annotated classes and automatically refreshing the context.
 * @param annotatedClasses one or more annotated classes,
 * e.g. {@link Configuration @Configuration} classes
 */
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
	this();//调用无参构造方法
	register(annotatedClasses);//注册Configuration配置类(可能有多个)
	refresh();//刷新方法
}
refresh()

进入到AbstractApplicationContext类中看refresh()方法。

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        // 刷新前的预处理,如environment环境信息、自定义环境信息的加入
        prepareRefresh();

        // Tell the subclass to refresh the internal bean factory.
        // 创建IOC容器bean工厂(beanFactory)
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // Prepare the bean factory for use in this context.
        // bean工厂(beanFactory)的预处理,属性的设置等操作
        // 上一步创建的beanFactory内属性基本都是没有值或者是默认值
        prepareBeanFactory(beanFactory);

        try {
            // Allows post-processing of the bean factory in context subclasses.
            // 没有逻辑实现,空方法,可以通过实现BeanFactoryProcessor,重写该方法,自定义逻辑
            postProcessBeanFactory(beanFactory);

            // Invoke factory processors registered as beans in the context.
            /*
             * 工厂processor处理器定义和所有bean的定义
             * 自定义bean包含单例bean、多例bean、懒加载bean
             * bean的定义在processor处理器定义的之前执行
             * 等待后续的实例化使用
             * 这一步必须在单例非懒加载bean初始化之前完成
             */
            invokeBeanFactoryPostProcessors(beanFactory);

            // Register bean processors that intercept bean creation.
            // bean实例化过程拦截的processor处理器,并注册到beanFactory中
            registerBeanPostProcessors(beanFactory);

            // Initialize message source for this context.
            // 初始化标签国际化
            initMessageSource();

            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            // 可通过继承,实现此方法,做个性化操作
            onRefresh();

            // Check for listener beans and register them.
            registerListeners();

            // Instantiate all remaining (non-lazy-init) singletons.
            // 初始化单例实例(非懒加载)
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            finishRefresh();
        }

        catch (BeansException ex) {
            //……
        }

        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}

这个方法包含很多东西,前面一系列的方法调用都是为后续的单例非懒加载bean的初始化做准备。

  • bean工厂的beanFacotry的实例化以及其内部属性的初始化
  • bean创建过程使用到处理器(processor)的前置处理和后置处理,所以这里需要在bean创建逻辑开始之前,将所有的处理器初始化完成
finishBeanFactoryInitialization()

进入到AbstractApplicationContext类中finishBeanFactoryInitialization()方法里面。

/**
 * Finish the initialization of this context's bean factory,
 * initializing all remaining singleton beans.
 * 完成上下文bean工厂的初始化
 * 初始化所有的单例bean
 */
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
	// Initialize conversion service for this context.
	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));
	}

	// Register a default embedded value resolver if no bean post-processor
	// (such as a PropertyPlaceholderConfigurer bean) registered any before:
	// at this point, primarily for resolution in annotation attribute values.
	if (!beanFactory.hasEmbeddedValueResolver()) {
		beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
			@Override
			public String resolveStringValue(String strVal) {
				return getEnvironment().resolvePlaceholders(strVal);
			}
		});
	}

	// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
	String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
	for (String weaverAwareName : weaverAwareNames) {
		getBean(weaverAwareName);
	}

	// Stop using the temporary ClassLoader for type matching.
	beanFactory.setTempClassLoader(null);

	// Allow for caching all bean definition metadata, not expecting further changes.
	beanFactory.freezeConfiguration();

	// Instantiate all remaining (non-lazy-init) singletons.
	// 核心方法:初始化单例bean(非懒加载bean)
	beanFactory.preInstantiateSingletons();
}

这个方法已经说明很清楚,是用来做bean工厂的初始化和单例非懒加载bean的初始化,以及加入到容器中。到这里说bean工厂的初始化可能会觉得在refresh()方法中不是已经完成了吗。但是那只是bean工厂的初期初始化,后期装配好的bean也是要丢入到bean工厂里面,也属于bean工厂初始化的一部分。

preInstantiateSingletons()

进入DefaultListableBeanFactory类中preInstantiateSingletons()方法看具体的bean实例化过程。

@Override
public void preInstantiateSingletons() throws BeansException {
	if (this.logger.isDebugEnabled()) {
		this.logger.debug("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.
	List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

	// Trigger initialization of all non-lazy singleton beans...
	for (String beanName : beanNames) {
		//代码1:尝试到本地获取bean,也就是从bean工厂里获取,bean工厂首次加载,这里获取的bd坑定为null
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		/*
		 *判断bd的属性
		 * isAbstract:是否是抽象类,抽象类是不能实例化的
		 * isSingleton:是否是单例
		 * isLazyInit:是否是懒加载
		 */
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
			if (isFactoryBean(beanName)) { //判断是否实现了FactoryBean接口
				final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
				boolean isEagerInit;
				if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
					isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
						@Override
						public Boolean run() {
							return ((SmartFactoryBean<?>) factory).isEagerInit();
						}
					}, getAccessControlContext());
				}
				else {
					isEagerInit = (factory instanceof SmartFactoryBean &&
							((SmartFactoryBean<?>) factory).isEagerInit());
				}
				if (isEagerInit) {
					getBean(beanName);//获取bean
				}
			}
			else {
				getBean(beanName);//获取bean
			}
		}
	}

	// ……

获取当前所有要初始化的bean并遍历,进入到循环中后,首先是判断有没有实现FactoryBean接口,根据不同的时间执行不同的getBean逻辑,这里以没有实现FactoryBean接口的实例化过程为主线。

getBean()、doGetBean()

进入第二个getBean()方法。getBean()方法中就一行代码。

return doGetBean(name, null, null, false);

此处无书,进入AbstractBeanFactory类中doGetBean()方法。

protected <T> T doGetBean(
		final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
		throws BeansException {

	final String beanName = transformedBeanName(name);
	Object bean;

	// Eagerly check singleton cache for manually registered singletons.
	// 获取单例bean,初始化过程,不会有bean存在,返回为null
	Object sharedInstance = getSingleton(beanName);
	if (sharedInstance != null && args == null) {
		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 = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	}

	else {
		// ……

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

		try {
			//使用RootBeanDefinition对当前bean的信息进行封装
			final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
			checkMergedBeanDefinition(mbd, beanName, args);

			// ……

			// Create bean instance.
			// 核心:创建bean实例
			if (mbd.isSingleton()) {
				// 从这里进入到getSingleton()方法,这里需要留意createBean()方法
				sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
					@Override
					public Object getObject() throws BeansException {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							destroySingleton(beanName);
							throw ex;
						}
					}
				});
				bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
			}

			else if (mbd.isPrototype()) {
				// ……
			}

			else {
				// ……
			}
		}
		catch (BeansException ex) {
			cleanupAfterBeanCreationFailure(beanName);
			throw ex;
		}
	}

	// ……
	return (T) bean;
}

主要的代码都加了注释,这个方法里面其实核心的就三步,第一是尝试从容器中获取bean,如果获取到直接返回,获取不到进入第二步,使用RootBeanDefinition来封装当前bean的信息。第三步创建bean实例,并将bean实例加入到bean工厂中。

getSingleton()

进入getSingleton()方法。

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
	Assert.notNull(beanName, "'beanName' must not be null");
	synchronized (this.singletonObjects) {
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null) {
			if (this.singletonsCurrentlyInDestruction) {
				throw new BeanCreationNotAllowedException(beanName,
						"Singleton bean creation not allowed while singletons of this factory are in destruction " +
						"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
			}
			/*
			 * 创建bean前的判断,里面的代码很简单
			 * 第一是判断创建bean检查集合是否包含当前的beanName
			 * 第二是加入到当前正在创建的集合中是否成功
			 */
			beforeSingletonCreation(beanName);
			// 设置是否为新单例bean的标记默认值为false
			boolean newSingleton = false;
			boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
			if (recordSuppressedExceptions) {
				this.suppressedExceptions = new LinkedHashSet<Exception>();
			}
			try {
				// 核心:调用创建单例bean的方法,也就是上一步lambda表达式内createBean方法
				singletonObject = singletonFactory.getObject();
				// 将是否为新单例bean的标记值设置为true
				newSingleton = true;
			}
			catch (IllegalStateException ex) {
				// Has the singleton object implicitly appeared in the meantime ->
				// if yes, proceed with it since the exception indicates that state.
				singletonObject = this.singletonObjects.get(beanName);
				if (singletonObject == null) {
					throw ex;
				}
			}
			catch (BeanCreationException ex) {
				if (recordSuppressedExceptions) {
					for (Exception suppressedException : this.suppressedExceptions) {
						ex.addRelatedCause(suppressedException);
					}
				}
				throw ex;
			}
			finally {
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = null;
				}
				//判断和beforeSingletonCreation类似
				afterSingletonCreation(beanName);
			}
			if (newSingleton) {
				// 将新创建的bean添加到缓存中
				addSingleton(beanName, singletonObject);
			}
		}
		return (singletonObject != NULL_OBJECT ? singletonObject : null);
	}
}

beforeSingletonCreation()方法中,做了一下两个判断:

  • !this.inCreationCheckExclusions.contains(beanName),当前需要创建的bean集合中是否存在当前的这个beanName,这个可以有效的保证当前创建为第一次创建;
  • !this.singletonsCurrentlyInCreation.add(beanName),将当前的beanName加入到当前正在创建的bean集合中。

这两个条件就保证当前没有其他位置正在创建这个bean,并将bean设置到正在创建的bean集合中,保证其他位置来创建的时候,能够得到有效的判断结果。
有before就有after,这里的afterSingletonCreation()前半段判断和beforeSingletonCreation()相同,但是后半段是将当前的beanName从bean集合中移除。

addSingleton()方法中,就是将当前创建的对象放入到对象缓存中,并将当前bean的起初需要注册的信息和起初bean封装信息移除。这些信息是用来为bean创建而存在的,待bean创建成功键入缓存中后,这个信息自然就会被移除。

createBean()

上面的创建前、后方法以及加入到缓存中的方法都已经解释,接下来要看一下核心方法createBean(),在AbstractAutowireCapableBeanFactory类中。

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
	if (logger.isDebugEnabled()) {
		logger.debug("Creating instance of bean '" + beanName + "'");
	}
	RootBeanDefinition mbdToUse = mbd;
	// ……
	try {
		// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
		/*
		 * 给一次尝试获取代理对象的机会,这里如果采用debug进入的话,可以看出返回的都是空
		 * 可能只会在特殊的场景下才会得到对应的结果,这里忽略
		 */
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if (bean != null) {
			return bean;
		}
	}
	catch (Throwable ex) {
		throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
				"BeanPostProcessor before instantiation of bean failed", ex);
	}
	// 核心:调用创建bean
	Object beanInstance = doCreateBean(beanName, mbdToUse, args);
	if (logger.isDebugEnabled()) {
		logger.debug("Finished creating instance of bean '" + beanName + "'");
	}
	return beanInstance;
}

这个方法里面主要需要注意的是具有迷惑性的resolveBeforeInstantiation(),这里可以忽略。接下里进入到doCreateBean()方法,还是在AbstractAutowireCapableBeanFactory类中。

doCreateBean()
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
        throws BeanCreationException {

    // Instantiate the bean.
    // 实例化当前的bean
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        //使用BeanWrapper对象封装当前需要创建的bean对象
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    //……
    
    // Initialize the bean instance.
    // 初始化bean实例
    Object exposedObject = bean;
    try {
        // 属性初始化
        populateBean(beanName, mbd, instanceWrapper);
        if (exposedObject != null) {
            // 核心:初始化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);
        }
    }

    //……

    return exposedObject;
}

这里分为两个部分,一个是使用BeanWrapper封装bean,然后通过populateBean()方法填充bean的数据信息。

initializeBean()

进入到initializeBean()方法中。

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    //……

    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的创建来说,前置处理没有太多的逻辑,主要是在后置处理里面,这个时候整个bean完成了全部的初始化,可以通过后置来对bean对象进行增强,常见的有AOP切面增强,生成代理对象等。

图例分析

上面说的内容很多,涉及到很多方法的跳转,可能会比较乱,通过下面的这个流程图,可以有更深入的了解。
在这里插入图片描述

通过这个流程图,加上对上面内容的理解,其实整个过程就是创建IOC容器,然后遍历初始化bean,然后将初始化后的bean丢入到容器中。相信通过上面的说明你对Spring IOC初始化过程有所了解。

但是上面源码分析的过程还少一步,但是图里面已经体现出来了,那就是getSingleton()方法的最后,会将新创建的bean放到IOC容器中,调用的方法是addSingleton()。看一下源码:

protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        // 这里就是将创建完成的bean实例SingletonObject放入到容器中
        this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
        this.singletonFactories.remove(beanName);
        this.earlySingletonObjects.remove(beanName);
        this.registeredSingletons.add(beanName);
    }
}

this.singletonObjects.put()方法中可以看出来,容器中存放bean是通过Map集合,但是需要注意的是这里的bean不是裸着的真正bean,而是通过封装后的封装bean。(后期更新bean实例的获取、以及FactoryBean和BeanFactory区别的时候,理解起来就可以更清晰)。

//singletonObjects存储bean的Map集合
/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

到这里真个IOC的加载过程主流程基本都说完了,但是还存在很多细枝末节的东西(比如多例是怎么实现的,懒加载又是怎么做的,增强的代理对象生成的过程等等),后续的文章还慢慢道来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿洞晓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值