博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring源码分析(一) IOC源码分析
阅读量:4074 次
发布时间:2019-05-25

本文共 8838 字,大约阅读时间需要 29 分钟。

spring-ioc源码分析

概述:spring是一个ioc容器,ioc就是我们把对象之间的依赖关系交给spring进行管理,比如说,我们在配置文件或者java配置类定义了bean的各种关系,spring负责加载这些bean,并维护了类之间的依赖,如果我们需要使用bean,直接getBean即可,这个就是spring作为Ioc容器的主要功能。

一、类介绍

1、ApplicationContext的总览

为了分析ioc的原理,我们先从可以接触到的applicationContent类进行入手,下面这个是我们的启动代码。

ApplicationContext context = new ClassPathXmlApplicationContext(xmlPath)。

以上代码就可以利用配置文件来启动一个 Spring 容器了,这段代码即是从配置文件加载bean到spring容器中,除了ClassPathXmlApplicationContext,我们还有AnnotationConfigApplicationContext(java配置)和FileSystemXmlApplicationContext (和ClassPathXml类似)。

下面我们先看看ApplicationContext的类结构,我们使用过的实现类主要是ClassPathXmlApplicationContext、AnnotationConfigApplicationContext。

ApplicationContext

           ConfigurableApplicationContext
            AbstractApplicationContext
            AbstractRefreshableApplicationContext                  GenericApplicationContext
                                                                                             AnnotationConfigApplicationContext
            AbstractRefreshableConfigApplicationContext
            AbstractXmlApplicationContext
           ClassPathXmlApplicationContext

2、BeanFactory的介绍

我们在说下BeanFactory这个接口,BeanFactory就是提供bean的接口,它的子接口在这基础上增加了扩展功能,我们上面的ApplicationContext也是实现了BeanFactory接口的,但是真正负责加载bean的是另外一个实现子类DefaultListableBeanFactory完成bean解析注册等工作。  // 可以从AbstractRefreshableConfigApplicationContext内找到DefaultListableBeanFactory类型的属性查看。

    BeanFactory   (ApplicationContext系列也有很多类或接口是实现BeanFactory)

    AutowireCapableBeanFactory    HierarchicalBeanFactory    ListableBeanFactory
    ConfigurableListableBeanFactory  // 继承了上面三个接口
    DefaultListableBeanFactory // 实现了ConfigurableListableBeanFactory  和 BeanDefinitionRegistry (负责注册beanDefinition)

3、BeanDefinition的介绍

在介绍BeanDefinition时,我们知道DefaultListableBeanFactory实现了BeanDefinitionRegistry接口功能用来加载并且注册bean。

我们先看看DefaultListableBeanFactory内部用什么来存储创建的bean,截取部分成员变量,beanDefinitionMap就是存储BeanDefinition信息。

    private final Map
beanDefinitionMap = new ConcurrentHashMap
(64);    private final Map
, String[]> allBeanNamesByType = new ConcurrentHashMap
, String[]>(64);    private final Map
, String[]> singletonBeanNamesByType = new ConcurrentHashMap
, String[]>(64);

BeanDefinition就是保存了我们的bean的名称、bean的类型,依赖那个类,以及是否单例等等信息。

 

二、流程分析

1、refresh主干方法

ClassPathXmlApplicationContext主要是调用refresh方法,refresh() 方法里面又调用了很多方法,详见下面。

public void refresh() throws BeansException, IllegalStateException {		synchronized (this.startupShutdownMonitor) {			prepareRefresh();			// 标记1---加载bean配置以及注册 			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();			prepareBeanFactory(beanFactory);			try {				postProcessBeanFactory(beanFactory);				invokeBeanFactoryPostProcessors(beanFactory);				registerBeanPostProcessors(beanFactory);				initMessageSource();				initApplicationEventMulticaster();				onRefresh();				registerListeners();				// 标记2--- 初始化所有的 singleton beans				finishBeanFactoryInitialization(beanFactory);				finishRefresh();			}		}	}

上面的标记1方法功能表示如何加载BeanDefinition到容器,标记2方法是创建Bean和初始化,其他都是一些附属处理功能。

我们先看看这些附属方法的主要功能:

prepareBeanFactory : 注册默认BeanPostProcessor用来实现一些功能。

invokeBeanFactoryPostProcessors : 执行BeanFactoryPostProcessor的各种实现类的方法。

registerBeanPostProcessors:注册 BeanPostProcessor 的实现类,这个方法会在初始前初始后增强bean,这里还未初始化的。

2、obtainFreshBeanFactory--加载注册bean

介绍完一些refresh的一些公共处理,我们就从refresh的起点方法obtainFreshBeanFactory来看看spring如何把各种bean从配置文件加载到内部的DefaultListableBeanFactory中。

obtainFreshBeanFactory实际调用obtainFreshBeanFactory方法。

protected final void refreshBeanFactory() throws BeansException {        if (hasBeanFactory()) {// ... }        try {           // 创建了DefaultListableBeanFactory,下面设置成this.beanFactory赋值            DefaultListableBeanFactory beanFactory = createBeanFactory();            beanFactory.setSerializationId(getId());            customizeBeanFactory(beanFactory);            // 实际加载方法            loadBeanDefinitions(beanFactory);             synchronized (this.beanFactoryMonitor) {                this.beanFactory = beanFactory;            }        }    }
protected DefaultListableBeanFactory createBeanFactory() {		return new DefaultListableBeanFactory(getInternalParentBeanFactory());	}

从上面我们可以看到refreshBeanFactory是创建一个DefaultListableBeanFactory来进行加载注册bean。

loadBeanDefinitions 系列调用栈,具体实现过于繁杂,我们知道主要是把配置的bean加载到DefaultListableBeanFactory即可。 (后续补充)

3、finishBeanFactoryInitialization  --- 创建bean和初始化bean

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {        // ....		beanFactory.setTempClassLoader(null);		// 允许缓存元数据,即以后不会变更 		beanFactory.freezeConfiguration();		// 实例化所有此时没有实例的单例bean  【主要调用方法】		beanFactory.preInstantiateSingletons();	}

从上面代码可以看到,finishBeanFactoryInitialization实际上是调用DefaultListableBeanFactory的preInstantiateSingletons方法。

public void preInstantiateSingletons() throws BeansException {				List
beanNames = new ArrayList
(this.beanDefinitionNames); for (String beanName : beanNames) { // 得到的BeanDefinition加工成RootBeanDefinition RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); // 不是抽象方法不是懒加载和多例 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { final FactoryBean
factory = (FactoryBean
) getBean(FACTORY_BEAN_PREFIX + beanName); boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { // .... } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean
) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } else { // 创建bean的核心方法 getBean(beanName); } } } // ....略 }

从上面可以看到,只有单例不是懒加载和多例的才会执行到get'Bean方法,并且这个方法调用doGetBean,这个方法超级长。

protected 
T doGetBean(final String name, final Class
requiredType, finalObject[] args, boolean typeCheckOnly)throws BeansException { final String beanName = transformedBeanName(name); Object bean; Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { // 缓存中取 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 父工厂取 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); if (args != null) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else { return parentBeanFactory.getBean(nameToLookup, requiredType); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dependsOnBean : dependsOn) { if (isDependent(beanName, dependsOnBean)) { throw new BeanCreationException(""); //循环依赖了 } registerDependentBean(dependsOnBean, beanName); getBean(dependsOnBean); // 依赖执行注册和getBean } } if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory
() { @Override public Object getObject() throws BeansException { try { // 创建bean 核心调用方法 return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { // 多例略.... } else { // 其他略.... } } } // .... return (T) bean; }

doGetBean方法,经过我的删减还有很长,主要包含从缓存取,如果存在返回,从父容器取,如果找到就返回,然后判断BeanDefinition内部的依赖bean,如果有依赖就注册这个依赖,并且同样执行getBean(),等于递归调用所有依赖的bean,执行一系列的getBean方法。最终,依赖都创建好了,当前Bean开始创建,执行的是createBean方法。实际调用的是doCreateBean。

doCreateBean的代码比较长,只贴主要的。

   Object exposedObject = bean;        try {            填充属性            populateBean(beanName, mbd, instanceWrapper);            if (exposedObject != null) {                初始化,包含BeanPostProcess的前置和后置处理                exposedObject = initializeBean(beanName, exposedObject, mbd);            }        }
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {	        // 各种awre的执行		invokeAwareMethods(beanName, bean);		if (mbd == null || !mbd.isSynthetic()) {        // 其他BeanPostProcess对本Bean的前置处理        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName);		}		try {            // 初始化方法执行			invokeInitMethods(beanName, wrappedBean, mbd);		}		catch (Throwable ex) {			// ...		}		if (mbd == null || !mbd.isSynthetic()) {        // 其他BeanPostProcess对本Bean的后置处理        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);		}		return wrappedBean;	}

从initializeBean方法,我们可以知道,spring一个bean的创建过程的一些Aware、BeanPostProcess、InitMethod等等生命周期的方法都在这个方法中体现了。详见:  // spring各种初始化方法大乱斗

至此,spring的IOC相关的代码以及spring容器的主要一些接口类都介绍完了。可以自己写一些例子,结合debug进行断点查看。

 

 

 

 

 

转载地址:http://yruni.baihongyu.com/

你可能感兴趣的文章
IntelliJ IDEA 下的svn配置及使用的非常详细的图文总结
查看>>
【IntelliJ IDEA】idea导入项目只显示项目中的文件,不显示项目结构
查看>>
ssh 如何方便的切换到其他节点??
查看>>
JSP中文乱码总结
查看>>
Java-IO-File类
查看>>
Java-IO-java的IO流
查看>>
Java-IO-输入/输出流体系
查看>>
Java实现DES加密解密
查看>>
HTML基础
查看>>
Java IO
查看>>
Java NIO
查看>>
Java大数据:Hbase分布式存储入门
查看>>
大数据学习:Spark RDD操作入门
查看>>
大数据框架:Spark 生态实时流计算
查看>>
大数据入门:Hive和Hbase区别对比
查看>>
大数据入门:ZooKeeper工作原理
查看>>
大数据入门:Zookeeper结构体系
查看>>
大数据入门:Spark RDD基础概念
查看>>
大数据入门:SparkCore开发调优原则
查看>>
大数据入门:Java和Scala编程对比
查看>>