Spring原理学习系列之五:IOC原理之Bean加载

引言

其实很多同学都想通过阅读框架的源码以汲取框架设计思想以及编程营养,Spring框架其实就是个很好的框架源码学习对象。我们都知道BeanSpring框架的最小操作单元,Spring框架通过对于Bean的统一管理实现其IOC以及AOP等核心的框架功能,那么Spring框架是如何把Bean加载到环境中来进行管理的呢?本文将围绕这个话题进行详细的阐述,并配合Spring框架的源码解析。

  • Bean创建
  • Bean加载流程
  • 总结

一、Bean创建

在搞清楚Spring框架如何加载Bean之前,我们需要明确Spring框架中的Bean是如何被创建的。那我们就不得不谈到BeanFactory。本文采用的AnnotationConfigApplicationContext来进行代码示例说明,它的类继承与实现结构如下所示。由图可知,BeanFactory是作为顶级接口的形式存在。

在这里插入图片描述
示例代码如下:

public class SpringTest {


    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(UserServiceImpl.class);

        IUserService userService = (UserServiceImpl)ac.getBean("userService");
        //3.执行bean中的方法
        userService.query();
    }
}

如示例代码所示,在new AnnotationConfigApplicationContext(UserService.class)创建context过程中,实际调用了AnnotationConfigApplicationContext的构造方法,其重载的构造方法如下所示:

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
...
	public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
		this();
		register(annotatedClasses);
		refresh();
	}
...
}

该构造方法主要完成三件事情:
1、this():初始化bean读取器以及扫描器,对应AnnotationConfigApplicationContext的无参构造函数,如下代码:

public AnnotationConfigApplicationContext() {
		//在IOC容器中初始化一个 注解bean读取器AnnotatedBeanDefinitionReader
		this.reader = new AnnotatedBeanDefinitionReader(this);
		//在IOC容器中初始化一个 按类路径扫描注解bean的扫描器
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

2、register(annotatedClasses):进行Bean配置类注册,如下代码:

public void register(Class... annotatedClasses) {
        Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
        this.reader.register(annotatedClasses);
    }

AnnotationConfigApplicationContext上下文中,通过AnnotatedBeanDefinitionReader调用register进行注解Bean的读取与注册操作。

public void register(Class<?>... annotatedClasses) {
		for (Class<?> annotatedClass : annotatedClasses) {
			registerBean(annotatedClass);
		}
	}

public void registerBean(Class<?> annotatedClass) {
		doRegisterBean(annotatedClass, null, null, null);
	}

<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
		//将注解类的数据格式转换为Bean容器中的AnnotatedGenericBeanDefinition
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
		//@Conditional装配条件判断是否需要跳过注册
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}
		//设置回调
		abd.setInstanceSupplier(instanceSupplier);
		 //解析bean作用域(单例或者原型),如果有@Scope注解,则解析@Scope,没有则默认为singleton 
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		//作用域写回BeanDefinition数据结构, abd中缺损的情况下为空,将默认值singleton重新赋值到abd
		abd.setScope(scopeMetadata.getScopeName());
		//生成bean配置类beanName
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

		//通用注解解析到abd结构中,主要是处理Lazy, primary DependsOn, Role ,Description这五个注解
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
		// @Qualifier特殊限定符处理
		if (qualifiers != null) {
			for (Class<? extends Annotation> qualifier : qualifiers) {
				if (Primary.class == qualifier) {
				// 如果配置@Primary注解,则设置当前Bean为自动装配autowire时首选bean	
					abd.setPrimary(true);
				}
				else if (Lazy.class == qualifier) {
				//设置当前bean为延迟加载
					abd.setLazyInit(true);
				}
				else {
					abd.addQualifier(new AutowireCandidateQualifier(qualifier));
				}
			}
		}
		for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
			customizer.customize(abd);
		}

		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		//按照名称将对应的bean注册到IOC容器中(在下一篇文章中进行介绍)
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

3、refresh():作用为刷新Spring的应用上下文;
刷新上下文的操作实际上是在AbstractApplicationContext中完成的。

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
		...
	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 准备上下文环境
			prepareRefresh();

			// 创建并初始化BeanFactory(这部分可以继续追踪,创建BeanFactory的过程)
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 填充BeanFactory功能
			prepareBeanFactory(beanFactory);

			try {
				// 提供子类覆盖的额外处理,即子类处理自定义的BeanFactoryPostProcess
				postProcessBeanFactory(beanFactory);

				// 激活各种BeanFactory处理器
				invokeBeanFactoryPostProcessors(beanFactory);

				 // 注册拦截Bean创建的Bean处理器,即注册 BeanPostProcessor
				registerBeanPostProcessors(beanFactory);

				 // 初始化上下文中的资源文件,如国际化文件的处理等
				initMessageSource();

				// 初始化上下文事件广播器
				initApplicationEventMulticaster();

				 // 给子类扩展初始化其他Bean
				onRefresh();

				// 在所有bean中查找listener bean,然后注册到广播器中
				registerListeners();

				// 初始化剩下的单例Bean(非延迟加载的)
				finishBeanFactoryInitialization(beanFactory);

				// 完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				//销毁已经创建的Bean
				destroyBeans();

				//重置容器激活标签
				cancelRefresh(ex);

				// 异常抛出
				throw ex;
			}

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

在这里插入图片描述

二、Bean加载

在这里插入图片描述
(图片来自于网络)
AnnotationConfigApplicationContext继承了AbstractApplicationContext

ublic abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
		...
		@Override
		public Object getBean(String name) throws BeansException {
			assertBeanFactoryActive();
			return getBeanFactory().getBean(name);
	}
		...
}

BeanFactory接口主要的实现是在AbstractBeanFactory中完成,doGetBean接收以下四个参数:
(1)name:准备获取 bean 的名字
(2)requiredType:准备获取 bean 的类型
(3)args:创建 bean 时传递的参数。这个参数仅限于创建 bean 时使用
(4)typeCheckOnly:是否为类型检查

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

...
	@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}
	
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;

		// 从缓存中或者实例工厂中获取 bean
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// 如果容器中没有找到,则从父类容器中加载
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

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

			try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// 获取依赖的 Bean
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						registerDependentBean(dep, beanName);
						try {
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				// 开始创建 Bean 实例,如果是单例的,那么会创建一个单例的匿名工厂,如果是原型模式的,则不需要创建单例的工厂的,其他的如 request、session 作用域的,则根据自身的需要
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						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);
				}

				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, () -> {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new BeanCreationException(beanName,
								"Scope '" + scopeName + "' is not active for the current thread; consider " +
								"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
								ex);
					}
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		// 类型检查,如果不能进行类型转换,则抛出异常
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			}
			catch (TypeMismatchException ex) {
				if (logger.isTraceEnabled()) {
					logger.trace("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}
...

}

三、总结

Spring IOC还有很多内容,本文只是管中窥豹,其他的部分将继续在后续的文章中进行详细介绍。

发布了88 篇原创文章 · 获赞 49 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/Diamond_Tao/article/details/103339593