Spring源码系列整体栏目
内容 | 链接地址 |
---|---|
【一】spring源码整体概述 | https://blog.csdn.net/zhenghuishengq/article/details/130940885 |
【一】通过refresh方法剖析IOC的整体流程 | https://blog.csdn.net/zhenghuishengq/article/details/131003428 |
spring底层源码整体概述
- 一,通过refresh方法剖析IOC的整体流程
- 1,prepareRefresh()
- 2,obtainFreshBeanFactory()
- 3,prepareBeanFactory()
- 4,postProcessBeanFactory()
- 5,invokeBeanFactoryPostProcessors()
- 6,registerBeanPostProcessors()
- 7,initMessageSource()
- 8,initApplicationEventMulticaster
- 9,onRefresh()
- 10,registerListeners()
- 11,finishBeanFactoryInitialization(重点)
- 11.1,dogetbean方法的粗略总结如下:
- 11.2,doCreateBean方法粗略总结如下(重点)
- 12,finishRefresh()
- 13,总结
一,通过refresh方法剖析IOC的整体流程
在上一篇中,已经粗略的谈了一下springIOC的整体执行流程,接下来通过源码的方式,深度的剖析底层的执行逻辑,这里依旧是针对IOC的底层实现,在对IOC有一定的了解之后,再研究AOP。
因此通过内部代码来查看容器的具体流程,这里主要研究的就是这个 refresh() 方法,无论是通过注解的方式还是通过XML的方式,都可以在获取上下文之后看到这个refresh方法,这里以xml的方式为例
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/a.xml");ctx.getBean("user");
接下来查看这个ClassPathXmlApplicationContext
这个实现类,主要就是初始化父类,加载资源,获取xml路径以及解析xml文件,最后再调用这个最终的refresh
方法。
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)throws BeansException {// 初始化父类 ,获得xml路径资源解析器super(parent);// 通过环境变量解析 xml路径,如加载上面的a.xmlsetConfigLocations(configLocations);if (refresh) {// 这个方法时spring是最重要的一个方法,甚至体系整个ioc的声明周期refresh(); }}
接下来就是进入这个最重要的refresh
方法,如下,每个方法有详细的注释。把这个refresh中的10多个方法吃透,spring源码基本上就没多大问题了。
@Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//1:准备刷新上下文环境prepareRefresh();//2:获取告诉子类初始化Bean工厂,不同工厂有不同的实现//并且将配置文件的属性值加载到当前工厂中ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//3:对bean工厂进行填充属性prepareBeanFactory(beanFactory);try {// 第四:留个子类去实现该接口,bean工厂的后置处理器postProcessBeanFactory(beanFactory);// 调用我们的bean工厂的后置处理器. //1. 会在此将class扫描成beanDefinition2.bean工厂的后置处理器调用invokeBeanFactoryPostProcessors(beanFactory);// 注册我们bean的后置处理器registerBeanPostProcessors(beanFactory);// 初始化国际化资源处理器.initMessageSource();// 创建事件多播器initApplicationEventMulticaster();// 这个方法同样也是留个子类实现的springboot也是从这个方法进行启动tomcat的.onRefresh();//把我们的事件监听器注册到多播器上registerListeners();// 实例化我们剩余的单实例bean.finishBeanFactoryInitialization(beanFactory);// 最后容器刷新 发布刷新事件(Spring cloud也是从这里启动的)finishRefresh();}}}
1,prepareRefresh()
在刷新上下文之前,有一个准备阶段
protected void prepareRefresh() {//设置基础环境标志this.closed.set(false);this.active.set(true);//初始化属性资源,留给子类实现的方法 initPropertySources();//用来校验我们容器启动必须依赖的环境变量的值getEnvironment().validateRequiredProperties();//创建一个早期事件监听器对象if (this.Listeners == null) {this.Listeners = new LinkedHashSet<>(this.applicationListeners);}else {// Reset local application listeners to pre-refresh state.this.applicationListeners.clear();this.applicationListeners.addAll(this.earlyApplicationListeners);}}
在这个initPropertySources()
方法中,比如我们自己写一个类重写了该方法,在该方法中设置了一个环境变量的值为test,启动的时候,我的环境变量中没有test值就会启动抛出异常
initPropertySources();
而在这个getEnvironment
方法中,其获取所有的环境变量相对来说比较复杂,在获取这个环境变量时需要先创建一个环境变量
this.environment = createEnvironment();//创建环境变量protected ConfigurableEnvironment createEnvironment() {return new StandardEnvironment();}
而在这个StandardEnvironment
对象中,需要继承这个AbstractEnvironment
父类,那么就需要先加载父类中的变量和属性,如一些System系统变量,属性等
public class StandardEnvironment extends AbstractEnvironment {/** System environment property source name: {@value} */public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";/** JVM system properties property source name: {@value} */public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";@Overrideprotected void customizePropertySources(MutablePropertySources propertySources) {propertySources.addLast(new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));}}
该阶段主要是设置一些环境变量标志,获取当前环境对象,并设置环境属性的值,设置监听器和发布事件的值。
2,obtainFreshBeanFactory()
在准备阶段获取到环境变量之后,接下来就是创建一个bean工厂。在这个Bean工厂中,有两个核心的bean工厂,分别是ListableBeanFactory
和ConfigurableBeanFactory
,同时还需要了解一个重要的bean工厂:DefaultListableBeanFactory
在初始化这个bean工厂对象的时候,会调用这个obtainFreshBeanFactory方法
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//获取刷新的bean工厂protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {//刷新bean工厂,有则销毁,无则创建新的refreshBeanFactory();//返回我们的bean工厂ConfigurableListableBeanFactory beanFactory = getBeanFactory();return beanFactory;}
在refreshBeanFactory刷新bean工厂中,就是创建了这个默认的bean工厂,而上下文创建的这个bean工厂,正是上面图片最底部的DefaultListableBeanFactory 对象,这里就获取到了bean工厂
protected DefaultListableBeanFactory createBeanFactory() {//创建默认的bean工厂return new DefaultListableBeanFactory(getInternalParentBeanFactory());}
在创建这个bean工厂之后,就会为这个bean工厂赋予默认值,并且loadBeanDefinitions是加载bean定义的阶段,其流程非常复杂,后续会重点讲解接在bean定义的过程。
/** * 为我们的Spring应用上下文对象创建我们的beanFactory */DefaultListableBeanFactory beanFactory = createBeanFactory();//为容器设置一个序列化IDbeanFactory.setSerializationId(getId());customizeBeanFactory(beanFactory);//加载bean定义loadBeanDefinitions(beanFactory);
加载完这个bean定义之后,会将这beanDefinition加入到beanDefinitionMap中,每一个bean定义中会有对应的具体的属性。
3,prepareBeanFactory()
在上一阶段创建了一个bean工厂,并且将配置文件解析成bean定义,然后将全部的bean定义加载到了工厂里面。接下来这一步就是为bean工厂进行一些属性填充,如设置一些类加载器,对象解析器,后置处理器等等
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {//设置bean工厂的类加载器为当前application应用的加载器beanFactory.setBeanClassLoader(getClassLoader());//为bean工厂设置我们标准的SPEL表达式解析器对象StandardBeanExpressionResolverbeanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));//为我们的bean工厂设置了一个propertityEditor 属性资源编辑器对象(用于后面的给bean对象赋值使用)beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));//后置处理器用来处理ApplicationContextAware接口的回调方法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);
最后就是注册一些工厂内部的bean,如一些环境,环境系统属性等
//环境beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());...
4,postProcessBeanFactory()
该方法是用于执行一些后置处理器的相关操作,该方法里面是一个空方法,相当于定义一个模板,留给子类做具体的实现。主要是用于子类做扩展实现。
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {}
5,invokeBeanFactoryPostProcessors()
顾名思义,就是用于执行bean工厂的后置处理器,在这里就可以执行修改bean定义的操作。通过这个方法上面的注释也可以知道,就是用于实例化和注册全部的bean工厂的后置处理器,并且必须在单例对象的初始化之前。在此步会将class扫描成beanDefinition。
/** * Instantiate and invoke all registered BeanFactoryPostProcessor beans, * respecting explicit order if given. * Must be called before singleton instantiation. */
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {}
在这个invokeBeanFactoryPostProcessors 类中,主要就是根据不同的优先级进行一个对应的加载
public static void invokeBeanFactoryPostProcessors(...){if (beanFactory instanceof BeanDefinitionRegistry){...}}
6,registerBeanPostProcessors()
第六步,就是注册bean的后置处理器。在bean工厂中,在初始化前后,可以调用bean的后置处理器,因此需要在使用前提前注册bean的后置处理器。
// 注册bean的后置处理器registerBeanPostProcessors(beanFactory);
其注册的流程如下,通过下面的注释也可以知道,就是初始化和注册全部的bean后置处理器
/** * Instantiate and register all BeanPostProcessor beans, * respecting explicit order if given. * Must be called before any instantiation of application beans. */
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory factory) {registerBeanPostProcessors(...);}
bean的后置处理器,在bean的整个生命周期都会进行调用,如aop的实现,@ConditionalOnClass条件的使用等
public static void registerBeanPostProcessors(...){}
7,initMessageSource()
除了注册这个bean工厂的后置处理器之外,还会进行国际化的初始操作
protected void initMessageSource() {//获取Bean工厂,一般是DefaultListBeanFactoryConfigurableListableBeanFactory beanFactory = getBeanFactory();//首先判断是否已有xml文件定义了id为messageSource的bean对象if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {//如果有,则从Bean工厂得到这个bean对象this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);// Make MessageSource aware of parent MessageSource.//当父类Bean工厂不为空,并且这个bean对象是HierarchicalMessageSource类型if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {//为HierarchicalMessageSource的实现类HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;//设置父类MessageSource,此处设置内部的parent messageSourceif (hms.getParentMessageSource() == null) {// Only set parent context as parent MessageSource if no parent MessageSource// registered already.hms.setParentMessageSource(getInternalParentMessageSource());}}if (logger.isTraceEnabled()) {logger.trace("Using MessageSource [" + this.messageSource + "]");}}else {// Use empty MessageSource to be able to accept getMessage calls.//如果没有xml文件定义信息源对象,新建DelegatingMessageSource类作为messageSource的Bean//因为DelegatingMessageSource类实现了HierarchicalMessageSource接口,而这个接口继承了MessageSource这个类//因此实现了这个接口的类,都是MessageSource的子类,因此DelegatingMessageSource也是一个MessageSourceDelegatingMessageSource dms = new DelegatingMessageSource();//给这个DelegatingMessageSource添加父类消息源dms.setParentMessageSource(getInternalParentMessageSource());this.messageSource = dms;//将这个messageSource实例注册到Bean工厂中beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);if (logger.isTraceEnabled()) {logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");}}}
8,initApplicationEventMulticaster
国际化之后还需要初始化应用程序事件的多播器,就是说从bean工厂中获取或者直接显示的new一个多播器赋值给我们的applicatoinContext对象
protected void initApplicationEventMulticaster() {//获取我们的bean工厂对象ConfigurableListableBeanFactory beanFactory = getBeanFactory();//判断容器中是没有有我们的applicationEventMulticaster 应用多播器组件if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {//直接显示的调用我们的getBean获取出来赋值给我们的applicationContext对象this.applicationEventMulticaster =beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);if (logger.isDebugEnabled()) {logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");}}//容器中没有的话else {//spring ioc显示的new 一个SimpleApplicationEventMulticaster对象保存在applicatoinContext对象中this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);//并且注入到容器中beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);}}
9,onRefresh()
这个方法也是留给子类去具体实现
protected void onRefresh() throws BeansException {// For subclasses: do nothing by default.}
10,registerListeners()
把事件的监听器注册到多播器上面
protected void registerListeners() {//获取容器中所有的监听器对象// 这个时候正常流程是不会有监听器的// (因为监听器不会在这之前注册,在initApplicationEventMulticaster后在registerListeners之前,只有一个可能在:在onRefresh里面注册了监听器)for (ApplicationListener << " />> listener : getApplicationListeners()) {//把监听器挨个的注册到我们的多播器上去getApplicationEventMulticaster().addApplicationListener(listener);}//获取bean定义中的监听器对象String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);//把监听器的名称注册到我们的多播器上for (String listenerBeanName: listenerBeanNames) {getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);}//在这里获取我们的早期事件Set < ApplicationEvent > earlyEventsToProcess = this.earlyApplicationEvents;// 在这里赋null。也就是值此之后都将没有早期事件了this.earlyApplicationEvents = null;if (earlyEventsToProcess != null) {//通过多播器进行播发早期事件for (ApplicationEvent earlyEvent: earlyEventsToProcess) {getApplicationEventMulticaster().multicastEvent(earlyEvent);}}}
至此,所有的准备工作就完成了。接下来就是通过bean工厂去创建个获取实例对象了。
11,finishBeanFactoryInitialization(重点)
在这一阶段,主要就是完成bean工厂要完成的事情,如实例化,属性填充和初始化等。如下图,里面主要是创建一些bean工厂类型的转换器,以及处理一些aspectj,实例化剩余的懒加载单例bean对象
而在这里面最重要的就是最后这个preInstantiateSingletons 实例化剩余的单例bean,在spring中,几乎所有的bean都是在这一步生成的。这里主要就是获取全部bean定义的名称,然后遍历这些名称,然后再合并这些bean定义,成为一个RootBean。最后判断这个RootBean是不是抽象的、类加载的或者单例的等
最终会调用一个getBean 方法,去真正的执行这个获取bean的流程。
/** * 该方法是一个空壳方法,没有任何的实现逻辑 真正的逻辑调用在doGetBean()中 * 该接口是实现了BeanFactory的getBean(String name)接口 */@Overridepublic Object getBean(String name) throws BeansException {//真正的获取bean的逻辑return doGetBean(name, null, null, false);}
而真正的获取这个bean的逻辑,正是这个 doGetBean 方法,这个方法的内容真的超级多。
/** * 返回bean的实例,该实例可能是单例bean 也有可能是原型的bean * @param name bean的名称 也有可能是bean的别名 * @param requiredType 需要获取bean的类型 * @param args 通过该参数传递进来,到调用构造方法时候发现有多个构造方法,我们就可以通过该参数来指定想要的构造方法了 * 不需要去推断构造方法(因为推断构造方法很耗时) * @param typeCheckOnly 判断当前的bean是不是一个检查类型的bean 这类型用的很少. * @return 返回一个bean实例 * @throws BeansException 如何bean不能被创建 那么就回抛出异常 */@SuppressWarnings("unchecked")protected < T > T doGetBean(final String name, @Nullable final Class < T > requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {/** * 在这里 传入进来的name 可能是 别名, 也有可能是工厂bean的name,所以在这里需要转换 */final String beanName = transformedBeanName(name);Object bean;//尝试去缓存中获取对象,一级二级三级缓存中查找Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {/** * /* * 如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回。但如果 * sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的 * bean 实例。如果用户想获取 FactoryBean 本身,这里也不会做特别的处理,直接返回 * 即可。毕竟 FactoryBean 的实现类本身也是一种 bean,只不过具有一点特殊的功能而已。 */bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);} else {/** * spring 只能解决单例对象的setter 注入的循环依赖,不能解决构造器注入 */if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}/** * 判断AbstractBeanFacotry工厂是否有父工厂(一般情况下是没有父工厂因为abstractBeanFactory直接是抽象类,不存在父工厂) * 一般情况下,只有Spring 和SpringMvc整合的时才会有父子容器的概念, * 比如我们的Controller中注入Service的时候,发现我们依赖的是一个引用对象,那么他就会调用getBean去把service找出来 * 但是当前所在的容器是web子容器,那么就会在这里的 先去父容器找 */BeanFactory parentBeanFactory = getParentBeanFactory();//若存在父工厂,切当前的bean工厂不存在当前的bean定义,那么bean定义是存在于父beanFacotry中if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {//获取bean的原始名称String nameToLookup = originalBeanName(name);//若为 AbstractBeanFactory 类型,委托父类处理if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);} else if (args != null) {//委托给构造函数 getBean() 处理return (T) parentBeanFactory.getBean(nameToLookup, args);} else {// 没有 args,委托给标准的 getBean() 处理return parentBeanFactory.getBean(nameToLookup, requiredType);}}/** * 方法参数 typeCheckOnly ,是用来判断调用 #getBean(...) 方法时,表示是否为仅仅进行类型检查获取 Bean 对象 * 如果不是仅仅做类型检查,而是创建 Bean 对象,则需要调用 #markBeanAsCreated(String beanName) 方法,进行记录 */if (!typeCheckOnly) {markBeanAsCreated(beanName);}try {final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);//检查当前创建的bean定义是不是抽象的bean定义checkMergedBeanDefinition(mbd, beanName, args);//依赖bean的名称String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {// 若给定的依赖 bean 已经注册为依赖给定的 bean// 即循环依赖的情况,抛出 BeanCreationException 异常for (String dep: dependsOn) {//beanName是当前正在创建的bean,dep是正在创建的bean的依赖的bean的名称if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}//保存的是依赖 beanName 之间的映射关系:依赖 beanName - > beanName 的集合registerDependentBean(dep, beanName);try {//获取depentceOn的beangetBean(dep);} catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}//创建单例beanif (mbd.isSingleton()) {//把beanName 和一个singletonFactory 并且传入一个回调对象用于回调sharedInstance = getSingleton(beanName, () - > {try {//进入创建bean的逻辑return createBean(beanName, mbd, args);} catch (BeansException ex) {//创建bean的过程中发生异常,需要销毁关于当前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();}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) {}}} catch (BeansException ex) {cleanupAfterBeanCreationFailure(beanName);throw ex;}}// Check if required type matches the type of the actual bean instance.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.isDebugEnabled()) {ClassUtils.getQualifiedName(requiredType) + "'", ex);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}return (T) bean;}
11.1,dogetbean方法的粗略总结如下:
1,首先获取bean的名字beanName,随后根据名字先尝试去一级缓存中获取
final String beanName = transformedBeanName(name);getSingleton(beanName);
2,如果缓存中没有获取到这个实例,则继续往下判断。如果是单例对象,则先解决循环依赖问题,如果是原型模式下也存在循环依赖,则直接抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}
3,接下来再判断当前工厂是否有父工厂,正常情况是没有,因为AbstractBeanFacotry是一个抽象类。只有在spring和springMVC 中才会出现父子容器的概念
getParentBeanFactory()
4,随后再获取beanDefinition,并检查当前的bean定义是不是抽象的,随后再判断当前bean是否存在依赖的bean,如果存在,则获取依赖bean的实例
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);//检查当前创建的bean定义是不是抽象的bean定义checkMergedBeanDefinition(mbd, beanName, args);//随后在判断当前bean是否存在依赖的beanString[] dependsOn = mbd.getDependsOn();
5,最后会判断一下获取到的beanDefinition是单例的还是原型的,如果是单例的bean定义则获取单例的bean对象,如果是一个原型的bean定义则获取一个原型的bean对象
if (mbd.isSingleton()) {getSingleton(String beanName, ObjectFactory<" />> singletonFactory);createBean(beanName, mbd, args);}else if (mbd.isPrototype()) {prototypeInstance = createBean(beanName, mbd, args);}else {...}
以单例模式为例,getSingleton 获取实例的流程主要如下
先从一级缓存的单例池中获取对象
//尝试从一级缓存的单例缓存池中获取对象Object singletonObject = this.singletonObjects.get(beanName);
如果从一级缓存中获取对象失败,则会标记该对象需要被创建,随后创建bean,最后加入到一级缓存中。
//如果获取对象失败,标记当前的bean马上就要被创建了beforeSingletonCreation(beanName);//初始化bean,这个过程其实是调用 createBean() 方法singletonObject = singletonFactory.getObject();//将标记移除afterSingletonCreation(beanName);//加入到一级缓存中addSingleton(beanName, singletonObject);
其主要方法是 singletonFactory.getObject() ,其内部就是调用了一个 createBean() 方法,在createBean() 方法中,其核心方法就是 doCreateBean 方法,该方法才是真正的创建bean对象的方法。在这个真正的去创建bean的方法中,其内容也超级多,这一步包含了 调用构造方法,给对象的属性赋值,初始化操作以及生成代理对象。最后将获取到的对象返回
protected Object doCreateBean(...) throws BeanCreationException {...}
再拿到这个bean的实例对象之后,就会做一个后置处理操作,将正在创建的bean从容器中删除
//主要做的事情就是把singletonsCurrentlyInCreation标记正在创建的bean从集合中移除afterSingletonCreation(beanName);
最后,将这个实例对象加入到一级缓存的单例池中
addSingleton(beanName, singletonObject);
6,判断当前bean是普通bean还是FactoryBean
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd)
7,至此,整个finishBeanFactoryInitialization 的流程结束。
11.2,doCreateBean方法粗略总结如下(重点)
1,第一步就是实例化一个对象,通过反射的方式实例化一个对象,可以通过构造器的方式等
//创建bean实例化,工厂方法、构造函数自动注入、简单初始化instanceWrapper = createBeanInstance(beanName, mbd, args);
2,在实例化之后,会有一个调用后置处理器的操作,主要用来解析一些 @AutoWired @Value等注解
//进行后置处理 @AutoWired @Value的注解的预解析applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
3,解决循环依赖问题,允许提前暴露实例化的对象,其属性值为默认值。就是将这个实例化的对象存入到三级缓存中,
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
4,这一步就是给实例化的对象进行属性填充 ,主要针对的是setter对象,这里就会将默认值变为具体的值
//属性赋值 给我们的属性进行赋值(调用set方法进行赋值)populateBean(beanName, mbd, instanceWrapper);
而属性注入有两种方式,一种是通过名称方式注入,一种是通过类型的方式注入
//根据bean的属性名称注入if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}//根据bean的类型进行注入if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}
6,属性填充之后就是初始化的操作
//进行对象初始化操作(在这里可能生成代理对象)exposedObject = initializeBean(beanName, exposedObject, mbd);
在初始化对象之前,会去判断该对象是否实现了XXXaware 接口,以及调用bean的后置处理器的方法,再调用初始化方法 进行初始化,最后又会调用bean的后置处理器的后置方法
protected Object initializeBean(...) {//若我们的bean实现了XXXAware接口进行方法的回调invokeAwareMethods(beanName, bean);//调用我们的bean的后置处理器的前置方法//@PostCust注解的方法applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);//调用初始化方法invokeInitMethods(beanName, wrappedBean, mbd);//调用bean的后置处理器的后置方法applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}
其步骤和上篇谈的bean工厂获取对象的步骤是一模一样的
7,到此为止,就是获取到了一个完整的实例对象,就可以将这个实例对象给返回了。
12,finishRefresh()
最后一步,就是最后容器刷新,发布刷新事件。如一些清除缓存,声明处理器,发布事件等等。
13,总结
从整个spring流程的源码分析来看,主要就是先读取配置文件,然后获取和设置一些环境变量,再初始化bean工厂,然后将读取到的文件读取到容器中,将这些配置文件先生成一个统一beanDifinition,期间也可以通过bean定义的后置处理器去修改这些生成的beandifinition,随后判断这些bean定义是单例的还是原型的,单例的通过bean工厂创建单例的对象,原型的创建原型的对象,bean工厂默认为DefaultListAbleBeanFactory,通过调用getbean方法从一级缓存中获取对象,如果获取失败,则进行一些实例化,属性填充,初始化的操作,期间会去实现Aware属性,bean的后置处理器等等,然后生成一个完整的对象,随后会将这个对象再加入到一级缓存中,再创建对象完成之后,就会去刷新容器。