Spring应用、原理以及粗读源码系列(一)--框架总述、以Bean为核心的机制(IoC容器初始化以及依赖注入)

总述:spring框架是如今J2EE开发最重要框架之一,为企业级应用提供一系列轻量级解决方案,比如:基于依赖注入的核心机制、基于AOP的声明式事务管理、与多种持久层技术整合、整合后端各种组件等等。贯穿了表现层、业务层、持久层,实现无缝整合。

文章结构:(1) 框架总述;(2)以Bean为核心的IOC/DI机制;


一、框架总述:

这里写图片描述
图选自疯狂Java讲义。文字参考:此博主此文章。本博主在此摘抄并补充下

(1)Core Container(核心容器):

包含有Core,Beans,Context,Expression Language模块。是框架的基础部分,提供IOC(控制反转)和依赖注入特性。这里的基础概念 是BeanFactory,它提供Factory模式的经典实现来消除对程序单例模式的需要,并真正地允许你从程序逻辑中分离出依赖关系和配置。

  • Core模块主要包含Spring框架基本的核心工具类,Spring的其他组件都要使用到这个包里的类,Core模块是其他组件的基本核心。当然你也可以在自己的应用系统中使用这些工具类。
  • Beans模块是所有应用都要用到的,它包含访问配置文件,创建和管理bean以及进行Inversion of Control/Dependency Injection(依赖注入)操作相关的所有类。
  • Context模块构建于Core和Beans模块基础之上,提供了一种类似于JNDI注册器的框架式的对象访问方法。Context模块集成了Beans的特性,为Spring核心提供了大量的扩展,添加了对国际化(例如资源绑定),事件传播,资源加载和对Context的透明创建的支持。Context模块同时也支持J2EE的一些特性,例如EJB(java企业Bean),JMX(Java Management Extensions,即Java管理扩展是一个为应用程序、设备、系统等植入管理功能的框架)和基础的远程处理。ApplicationContext接口是Context模块的关键。
  • Expression Language 模块提供了一个强大的表达式语言用于在运行时查询和操纵对象。它是JSP2.1规范中定义的unifed expression language的一个扩展。该语言支持设置/获取属性的值,属性的分配,方法的调用,访问数组上下文(accession the context of arrays),容器和索引器,逻辑和算数运算符,命名变量以及从Spring的IOC容器中根据名称检索对象。它也支持list投影,选择和一般的list聚合。

(2)WEB层:

Web上下文模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文。所以Spring框架支持与Jakarta Struts的集成。Web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。Web层包含了Web,Web-Servlet,Web-Struts和Web-Porlet模块,具体说明如下。

  • Web-Servlet模块web.servlet.jar:该模块包含Spring的model-view-controller(MVC)的实现。Spring的MVC框架使得模型范围内的代码和web forms之间能够清楚地分离开来,并与Spring框架的其他特性集成在一起。
  • Web模块:提供了基础的面向Web的集成特性。例如,多文件上传,使用servlet listeners初始化IOC容器以及一个面向Web的应用上下文。它还包含Spring远程支持中Web的相关部分。
  • Web-Porlet模块:提供了用于Portlet环境和Web-Servlet模块的MVC的实现。
  • spring4.0以后加入了对websocket技术的支持.目的是浏览器与服务端建立全双工的通信方式,解决http请求-响应带来过多的资源消耗,同时对特殊场景应用提供了全新的实现方式,比如聊天、股票交易、游戏等对对实时性要求较高的行业领域。

(3)Data Access/Integration.持久层:

Data Access/Integration层包含有JDBC,ORM,OXM,JMS和Transaction模块,其中:

  • JDBC模块提供了一个JDBC抽象层,它可以消除冗长的JDBC编码和解析数据库厂商特有的错误代码。这个模块包含了Spring对JDBC数据访问进行封装的所有类。
  • ORM(Object Relational Mapping对象关系映射)模块为流行的对象-关系映射API,如JPA,JDO,Hibernate,iBatis等,提供了一个交互层。利用ORM封装包,可以混合使用所有Spring提供的特性进行O/R映射。如前边提到的简单声明性事务管理。

Spring框架插入了若干个ORM框架,从而提供了ORM的对象关系工具,其中包括JDO,hibernate和MyBatis。所有这些都遵从Spring的通用事务和DAO异常层次结构。

  • OXM模块提供了一个对Object/XML映射实现的抽象层,Object/XML映射实现包括JAXB(JAXB能够使用Jackson对JAXB注解的支持实现(jackson-module-jaxb-annotations),既方便生成XML,也方便生成JSON,这样一来可以更好的标志可以转换为JSON对象的JAVA类。
  • JMS(Java Messaging Service)模块主要包含了一些制造和消费消息的特性。
  • Transaction模块支持编程和声明性的事务管理,这些事务类必须实现特定的接口,并且对所有的POJO(实际就是普通JavaBeans)都适用。

(4)切面层:

1. AOP模块提供了一个符合AOP联盟标准的面向切面编程的实现,它让你可以定义例如方法拦截器和切点。从而将逻辑代码分开,降低它们之间的耦合性。利用source-level的元数据功能,还可以将各种行为信息合并到你的代码中,这有点像.Net技术中的attribute概念。

通过配置管理特性,SpringAOP模块直接将面向切面的编程功能集成到了Spring框架中,所以可以很容易地使Spring框架管理的任何对象支持AOP。Spring AOP模块为基于Spring的应用程序中的对象提供了事务管理服务。通过使用Spring AOP,不用依赖EJB组件,就可以将声明性事务管理集成到应用程序中。

2. Aspects模块提供了对AspectJ(一个面向切面的框架,它扩展了Java语言)的集成支持。

3.Instrumentation模块提供了class instrumentation 支持和classloader实现,使得可以在特定的应用服务器上使用。

(5)Test层:

此层支持使用JUnit和TestNG对Spring组件进行测试。

@RunWith(SpringJUnit4ClassRunner.class) // 使用Springtest测试框架
@ContextConfiguration("/spring/spring-*.xml") // 加载配置

二、以Bean为核心的IOC/DI机制:

总述理论核心:在spring中,所有的对象都会被spring核心容器管理。一切对象统称为Bean。

Spring容器可通过XML配置文件或者注解去管理这堆Bean。

(1)定义以及原理:

依赖注入(IOC/DI):spring容器负责将被依赖对象赋值给调用者的成员变量--相当于为调用者注入它依赖的实例。

依赖关系:A对象需要调用B对象方法的情况--A依赖B。

原理:

1. 原始做法:调用者主动创建被依赖对象,然后再调用被依赖对象的方法。

调用者需要通过像“new 对象”的操作去创建对象。

缺点:必然导致调用者与被依赖对象实现类的硬编码耦合。(因为我不想知道你的创建过程、也不想主动去创建你)

2. 简单工厂模式:调用者先找到被依赖对象的工厂,然后主动通过工厂去获取被依赖对象,最后再调用被依赖对象的方法。

调用者面向被依赖对象的接口编程;将被依赖对象的创建交给工厂;调用者通过工厂来获得被依赖组件。

缺点:调用组件需要主动通过工厂去获取被依赖对象,必然带来调用组件与被依赖对象工厂的耦合。(同样,我也不想知道你这个工厂存在,我只想要个依赖对象)

3.Spring框架下的依赖注入:框架为调用者注入它依赖的实例。

优点:程序无须例会被依赖对象的实现,也无须主动定位工厂。只需被动等待IOC容器分配依赖对象。

(2)应用:

依赖注入分为两种:[一]设值注入;[二]构造注入;

1. 设值注入:指IOC容器通过成员遍历的setter方法来注入被依赖对象。

使用方法:可见我们没有硬编码上去创建依赖对象

<?xml version="1.0" encoding="GBK"?>
<!-- Spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    <!-- 配置chinese实例,其实现类是Chinese类 -->
    <bean id="chinese" class="com.fuzhu.Chinese">
        <!-- 驱动调用chinese的setAxe()方法,将容器中stoneAxe作为传入参数 -->
        <property name="axe" ref="stoneAxe"/>
    </bean>
    <!-- 配置Axe实例 -->
    <bean id="axe" class="com.fuzhu.Axe"/>
    
</beans>

public class Chinese 
{
    private Axe axe;//定义个斧头引用
    // 设值注入所需的setter方法
    public void setAxe(Axe axe)
    {
        this.axe = axe;
    }
    // 实现依赖对象的方法useAxe方法
    public void useAxe()
    {
        // 调用axe的chop()方法,
        // 表明Chinese 对象依赖于axe对象
        System.out.println(axe.chop());
    }
}
//斧头类
public class Axe 
{
    public String chop()
    {
        return "石斧砍柴好慢";
    }
}

写个test类

public class BeanTest
{
    public static void main(String[] args)throws Exception
    {
        // 创建Spring容器
        ApplicationContext ctx = new
            ClassPathXmlApplicationContext("beans.xml");
        // 获取chinese 实例
        Chinese p = ctx.getBean("chinese" , Chinese.class);
        // 调用useAxe()方法
        p.useAxe();
    }
}

2. 构造注入:IOC容器使用构造器来注入被依赖对象。

在构造实例时,已经为其完成了依赖关系的初始化。本质就是当执行带参数的构造器时,就可利用构造器参数对成员变量执行初始化。《contructopr-arg... /》

使用方法:

<?xml version="1.0" encoding="GBK"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    <!-- 配置chinese实例,其实现类是Chinese -->
    <bean id="chinese" class="com.fuzhu.Chinese">
        <!-- 下面只有一个constructor-arg子元素,
            驱动Spring调用Chinese带一个参数的构造器来创建对象 -->
        <constructor-arg ref="axe" type="com.fuzhu.Axe"/>
    </bean>
    <!-- 配置Axe实例-->
    <bean id="axe" class="com.fuzhu.StoneAxe"/>
</beans>

public class Chinese 
{
    private Axe axe;
    // 构造注入所需的带参数的构造器
    public Chinese(Axe axe)
    {
        this.axe = axe;
    }
    // 实现依赖对象的方法useAxe()方法
    public void useAxe()
    {
        // 调用axe的chop()方法
        // 表明Chinese 对象依赖于axe对象
        System.out.println(axe.chop());
    }
}
public class  Axe
{
    public String chop()
    {
        return "石斧砍柴好慢";
    }
}

3. 注解注入装配: 以后再讲,其实是基于前两种注解方式实现的。

(3)IOC/DI依赖注入源码理解:(基于spring4.1.7)

重点理解两个过程:IoC容器初始化过程以及IoC容器依赖注入过程。

其实就是:资源定位、资源装载、资源解析、Bean生成,Bean注册、Bean依赖注入这几个过程(前五属于初始化过程)。方法:eclipse断点ClassPathXmlApplicationContext调用,不断跳进去,就看到spring执行栈了。

1. IoC容器初始化过程:

这里写图片描述

以上图思路进行详细讲述

初始化总过程:资源定位(确定工厂创建和bean的配置文件)--->资源装载(在文件系统路径上对IOC配置文件、bean配置进行加载)--->资源解析(解析bean配置,解析xml元素)--->生成bean(根据DOM资源解析成bean)--->在IoC容器中注册(交给IoC容器管理,还有依赖注入的权限)

这里写图片描述

整体过程大致如上图(从下往上看的栈,):保存配置,并刷新工厂-->创建载入BeanFactory-->创建XmlBeanDefinitionReader-->创建处理每一个Resource-->转换成Document对象-->处理XML每个元素-->解析注册bean


[一]资源定位:

追踪:我们可在此句获取工厂前设断点然后debug追踪进去,查看IoC的资源定位
ApplicationContext ctx = new ClassPathXmlApplicationContext("/spring/spring-*.xml");

然后一路跳进去:

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[]{configLocation}, true, (ApplicationContext)null);
}
/*
    此处为资源定位核心调用层
*/
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
        super(parent);//有前面类图 可 以知道,最终 父类 为AbstractApplicationContext
        this.setConfigLocations(configLocations);//调用资源定位设置方法,然后我们跳进去寻找此方法位置,如下面代码
        if(refresh) {//接着执行容器刷新方法
            this.refresh();
        }

    }
    //这个是追踪上去的ClassPathXmlApplicationContext父类
public AbstractXmlApplicationContext(ApplicationContext parent) {
        super(parent);
    }
    //再追踪AbstractXmlApplicationContext的父类AbstractRefreshableConfigApplicationContext。然后它拥有了以下方法,从而
public void setConfigLocation(String location) {
        this.setConfigLocations(StringUtils.tokenizeToStringArray(location, ",; \t\n"));
    }
/*
    资源定位方法
*/
    public void setConfigLocations(String... locations) {
        if(locations != null) {
            Assert.noNullElements(locations, "Config locations must not be null");
            this.configLocations = new String[locations.length];
// 该方法调用 SystemPropertyUtils.resolvePlaceholders(path) ;对 path 中的占位 符进行替换, eg : path 路径中含有 ${user.dir} ,则将替换为: System.getProperty(user.dir);
            for(int i = 0; i < locations.length; ++i) {
                this.configLocations[i] = this.resolvePath(locations[i]).trim();
            }
        } else {
            this.configLocations = null;
        }

    }

根据资源定位核心调用层,我们可以看到他必执行AbstractApplicationContext中的refresh方法,执行容器刷新。部分叙述参考此博主此文章

public void refresh() throws BeansException, IllegalStateException {
        Object var1 = this.startupShutdownMonitor;
        //加锁同步了
        synchronized(this.startupShutdownMonitor) {
         //调用容器准备刷新的方法,获取 容器的当时时间,同时给容器设置同步标识  
            this.prepareRefresh();
            //告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从子类的refreshBeanFactory()方法启动  
            //并获取beanFactory
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            //为BeanFactory配置容器特性,例如类加载器、事件处理器等  
            this.prepareBeanFactory(beanFactory);

            try {
                //为容器的某些子类指定特殊的BeanPost事件处理器  
                this.postProcessBeanFactory(beanFactory);
                //调用所有注册的BeanFactoryPostProcessor的Bean  
                this.invokeBeanFactoryPostProcessors(beanFactory);
                //为BeanFactory注册BeanPost事件处理器.  
                 //BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件  
                this.registerBeanPostProcessors(beanFactory);
                //初始化信息源,和国际化相关.  
                this.initMessageSource();
                //初始化容器事件传播器. 
                this.initApplicationEventMulticaster();
                //调用子类的某些特殊Bean初始化方法
                this.onRefresh();
                //为事件传播器注册事件监听器.  
                this.registerListeners();
                //初始化所有剩余的单态Bean.  
                this.finishBeanFactoryInitialization(beanFactory);
                 //初始化容器的生命周期事件处理器,并发布容器的生命周期事件 
                this.finishRefresh();
            } catch (BeansException var5) {
                //打印警告
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var5);
                 //销毁以创建的单态Bean  
                this.destroyBeans();
                 //取消refresh操作,重置容器的同步标识.  
                this.cancelRefresh(var5);
                throw var5;
            }

        }
    }
    //获取工厂,让子类刷新内部 bean 工厂。
    /*
    关闭前面所有 bean 工厂,为新的上下文环境初始化一个新的 bean 工厂。这里需要子类来 协助完成资源位置定义 ,bean 载入和向 IOC 容器注册的过程
    容器真正调用的是其子类AbstractRefreshableApplicationContext实现的 refreshBeanFactory()方法
    见下方
    */
   protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        this.refreshBeanFactory();//子类实现,调用子类的实现
        ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory);
        }

        return beanFactory;
    }

 

AbstractRefreshableApplicationContext实现的refreshBeanFactory

/*
在这个方法中,先判断BeanFactory是否存在,如果存在则先销毁beans并关闭beanFactory,接着创建DefaultListableBeanFactory,并调用loadBeanDefinitions(beanFactory)装载bean
*/
protected final void refreshBeanFactory() throws BeansException {  
       if (hasBeanFactory()) {//如果已经有容器,销 毁 容器中的bean,关闭容器  
           destroyBeans();  
           closeBeanFactory();  
       }  
       try {  
            //创建IoC容器  
            DefaultListableBeanFactory beanFactory = createBeanFactory();  
            beanFactory.setSerializationId(getId());  
           //对IoC容器进行定制化,如设置启动参数,开启注解的自动装配等  
           customizeBeanFactory(beanFactory);  
           //调用载入Bean定义的方法,主要这里使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器  
           loadBeanDefinitions(beanFactory);  
           synchronized (this.beanFactoryMonitor) {  
               this.beanFactory = beanFactory;  
           }  
       }  
       catch (IOException ex) {  
           throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);  
       }  
   }
    //为刷新准备上下文环境
protected void prepareRefresh() {
        this.startupDate = System.currentTimeMillis();
        this.active.set(true);
        if(this.logger.isInfoEnabled()) {
            this.logger.info("Refreshing " + this);
        }

        this.initPropertySources();
        this.getEnvironment().validateRequiredProperties();
    }

总的来说:资源定位做的就是:确定工厂位置,执行工厂初始化并刷新,建立好bean资源加载路径。等待bean资源装载。


[二]资源装载

设置工厂配置,刷新容器后,还要把我们的bean配置给资源加载器。

目标:拿到资源加载器,可以classpath:那样直接拿到资源装载。

在这之前,很有必要大家一起区分:不同类中的loadBeanDefinitions解析职责。

在AbstractXmlApplicationContext类中,职责为:对applicationContext.xml的解析操作,就是解析工厂的那个xml

在AbstractBeanDefinitionReader类中,职责为:从指定的资源加载bean定义,真正实现在其子类,这里是做了些兼容性错误处理。

在XmlBeanDefinitionReader类中,是AbstractBeanDefinitionReader的子类,而且是一个真正的实现类 ,是实现BeanDefinitionReader接口的loadBeanDefinitions(Resource var1) 等方法的关键解析类。职责为:读取并真正解析 xml 文件。

AbstractRefreshableApplicationContext中只定义了抽象的loadBeanDefinitions方法,容器真正调用的是其子类AbstractXmlApplicationContext对该方法的实现。(全局搜索SHIFT)
/*
    !!!!资源装载以此为主线!!!这个是哪里的呢??AbstractXmlApplicationContext实现的
*/
 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
 //从beanfactory拿到reader
  // 这里使用XMLBeanDefinitionReader来载入bean定义信息的XML文件
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        //这里配置reader的环境,其中ResourceLoader是我们用来定位bean定义信息资源位置的
        ///因为上下文本身实现了ResourceLoader接口,所以可以直接把上下文作为ResourceLoader传递给XmlBeanDefinitionReader。容器本身也是一个资源加载器        
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
         //当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制  
        this.initBeanDefinitionReader(beanDefinitionReader);
         //这里转到定义好的XmlBeanDefinitionReader中对载入bean信息进行处理
        this.loadBeanDefinitions(beanDefinitionReader);
    }

由上面代码得知进入AbstractXmlApplicationContext的loadBeanDefinitions(XmlBeanDefinitionReader参数)

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
         //获取Bean定义资源的定位  
        Resource[] configResources = this.getConfigResources();
         //调用XmlBeanDefinitionReader来载入bean定义信息。 也就是AbstractBeanDefinitionReader类的loadBeanDefinitions去读取Bean资源
        if(configResources != null) {
            reader.loadBeanDefinitions(configResources);
        }
        //例子中使用了的是ClassPathXmlApplicationContext,所以跑下面的bean装载方法
        String[] configLocations = this.getConfigLocations();
        if(configLocations != null) {
            reader.loadBeanDefinitions(configLocations);
        }

    }

接着根据上面继续追踪,到了AbstractBeanDefinitionReader类的loadBeanDefinitions方法

 public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
 //这里得到当前定义的ResourceLoader,默认的 我 们 使用DefaultResourceLoader
        ResourceLoader resourceLoader = this.getResourceLoader();
        //如果没有找到我们需要的ResourceLoader,直接抛出异常
        if(resourceLoader == null) {
            throw new BeanDefinitionStoreException("Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
        } else {
            int loadCount;
            if(!(resourceLoader instanceof ResourcePatternResolver)) {
            // 这里处理我们在定义位置时使用的各种pattern,需要ResourcePatternResolver来完成
                Resource resource = resourceLoader.getResource(location);
                loadCount = this.loadBeanDefinitions((Resource)resource);
                if(actualResources != null) {
                    actualResources.add(resource);
                }

                return loadCount;
            } else {
                try {
                 // 这里通过ResourceLoader来完成位置定位
                    Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
                    // 这里已经把一个位置定义转化为Resource接口,可以供XmlBeanDefinitionReader来使用了
                    loadCount = this.loadBeanDefinitions(resources);
                    if(actualResources != null) {
                        Resource[] var6 = resources;
                        int var7 = resources.length;

                        for(int var8 = 0; var8 < var7; ++var8) {
                            Resource resource = var6[var8];
                            actualResources.add(resource);
                        }
                    }

                    if(this.logger.isDebugEnabled()) {
                        this.logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
                    }

                    return loadCount;
                } catch (IOException var10) {
                    throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", var10);
                }
            }
        }
    }

所以,AbstractBeanDefinitionReader的loadBeanDefinitions方法源码分析可以看出该方法做了以下两件事:

(1)首先,调用资源加载器的获取资源方法resourceLoader.getResource(location),获取到要加载的资源。

(2)其次,真正执行加载功能是其子类XmlBeanDefinitionReader实现的loadBeanDefinitions方法。

另外,此时调用的是DefaultResourceLoader中的getSource()方法定位Resource。

然后我们再仔细看下各个类想拿到资源加载器就是通过getResourceLoader,拿到AbstractBeanDefinitionReader类定义的resourceLoader。这样的话,我们可通过此方式在工程spring下的任何地方拿到资源加载器,“随处加载”了。

public interface ResourceLoader {
    String CLASSPATH_URL_PREFIX = "classpath:";

    Resource getResource(String var1);//拿到资源

    ClassLoader getClassLoader();//拿到类加载器
}

总的来说,资源装载就是:根据之前确定好的bean资源配置路径,拿到资源、拿到加载器,并把bean配置丢进XmlBeanDefinitionReader。等待Bean资源解析。


[三]Bean资源解析:其实就是刚我们遇到的XmlBeanDefinitionReader类啦。真正去解析xml。解析的关注重心请注意到doLoadBeanDefinitions方法,从这里进行分发。从而到下一部生成bean对象。

目标:将XML文件转为DOM对象。进而交DocumentLoader和DocumentBuilderFactory处理dom对象给doLoadBeanDefinitions方法,从而为bean生成作铺垫

//这里是载入XML形式Bean定义资源文件方法 
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        Assert.notNull(encodedResource, "EncodedResource must not be null");
        if(this.logger.isInfoEnabled()) {
            this.logger.info("Loading XML bean definitions from " + encodedResource.getResource());
        }
         //获取当前的线程变量,它是用于保存处理的resource的  
        Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();
        if(currentResources == null) {
            currentResources = new HashSet(4);
            this.resourcesCurrentlyBeingLoaded.set(currentResources);//保存当前的resource 
        }
        if(!((Set)currentResources).add(encodedResource)) {
            throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");
        } else {
            int var5;
            try {
             //将资源文件转为InputStream的IO流 
                InputStream inputStream = encodedResource.getResource().getInputStream();

                try {
                 //从InputStream中得到XML的解析源   
                    InputSource inputSource = new InputSource(inputStream);
                    if(encodedResource.getEncoding() != null) {
                        inputSource.setEncoding(encodedResource.getEncoding());
                    }
            //这里是具体的读取过程  
                    var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
                } finally {
                //关闭从Resource中得到的IO流   
                    inputStream.close();
                }
            } catch (IOException var15) {
                throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), var15);
            } finally {
                ((Set)currentResources).remove(encodedResource);
                if(((Set)currentResources).isEmpty()) {
                    this.resourcesCurrentlyBeingLoaded.remove();
                }

            }

            return var5;
        }
    }
//从特定XML文件中实际载入Bean定义资源的方法 ,就是转成dom对象后交给这里去进一步处理从而转换出bean
    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
        try {
        //将XML文件转换为DOM对象,解析过程由documentLoader实现
            Document doc = this.doLoadDocument(inputSource, resource);
             //这里是启动对Bean定义解析的详细过程,该解析过程会用到Spring的Bean配置规则
            return this.registerBeanDefinitions(doc, resource);
        } catch (BeanDefinitionStoreException var4) {
            throw var4;
        } catch (SAXParseException var5) {
            throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + var5.getLineNumber() + " in XML document from " + resource + " is invalid", var5);
        } catch (SAXException var6) {
            throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", var6);
        } catch (ParserConfigurationException var7) {
            throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, var7);
        } catch (IOException var8) {
            throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, var8);
        } catch (Throwable var9) {
            throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, var9);
        }
    }

然后沿着doLoadDocument继续追踪,追踪到一个接口DocumentLoader和一个实现类DefaultDocumentLoader。以下是DefaultDocumentLoader这个实现类的部分代码

public Document loadDocument(InputSource inputSource, EntityResolver entityResolver, ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
  //创建文件解析器工厂  
        DocumentBuilderFactory factory = this.createDocumentBuilderFactory(validationMode, namespaceAware);
        if(logger.isDebugEnabled()) {
            logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
        }
//创建文档解析器  
        DocumentBuilder builder = this.createDocumentBuilder(factory, entityResolver, errorHandler);
        //解析Spring的Bean定义资源
        return builder.parse(inputSource);
    }
    //再根据上面方法追踪到它也执行了本类的一个方法:
    //调用了Javaee的JAXP标准,根据定位的Bean定义资源文件,加载读入并转换成为Document对象过程完成
protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory, EntityResolver entityResolver, ErrorHandler errorHandler) throws ParserConfigurationException {
        DocumentBuilder docBuilder = factory.newDocumentBuilder();
        if(entityResolver != null) {
            docBuilder.setEntityResolver(entityResolver);
        }

        if(errorHandler != null) {
            docBuilder.setErrorHandler(errorHandler);
        }

        return docBuilder;
    }

总的来说:Bean资源解析就是,先通过 XML解析器讲Bean定义资源文件转换得到Document对象,但是这堆Document对象没有按照spring的Bean规则的,所以不可直接转换成bean对象。然后完成XML解析变成Document对象后,就调用spring的解析方法按照Spring的Bean规则去对Document进行解析,生成Bean对象。


[四]生成Bean:还是关注XmlBeanDefinitionReader类的doLoadBeanDefinitions方法,他进行了一个调用:registerBeanDefinitions。

//按照Spring的Bean语义要求 将Bean 定 义  资源解析并转换为容器内部数据结构 
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//得到BeanDefinitionDocumentReader来对xml格式的BeanDefinition解析  
        BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
        //读取环境的配置设置
        documentReader.setEnvironment(this.getEnvironment());
        //获得容器中注册的Bean数量  
        int countBefore = this.getRegistry().getBeanDefinitionCount();
         //解析过程入口,这里使用了委派模式,BeanDefinitionDocumentReader只是个接口,//具体的解析实现过程有实现类DefaultBeanDefinitionDocumentReader完成 
        documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
        //统计解析的Bean数量
        return this.getRegistry().getBeanDefinitionCount() - countBefore;
    }
    //在此方法真正去转化document对象成为bean
 protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
        return (BeanDefinitionDocumentReader)BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
    }

接下来就是document元素的一个个解析,然后转化成bean对象了。我们根据上面的解析入口可以追踪到 BeanDefinitionDocumentReader接口的实现类DefaultBeanDefinitionDocumentReader。在这个类进行详细的document元素解析成我们平常工程用的bean。但本博主不打算继续看了,因为对我们掌握spring的IOC原理并不影响。

[五]在IoC容器注册解析生成的Bean

目标:到IoC容器注册

我们能猜到他在类DefaultBeanDefinitionDocumentReader生成bean后必然会丢给IoC容器去注册,交给它管理。但是我们怎么找到呢??根据上面生成bean中的解析入口,我们CTRL+F查registerBeanDefinitions。

再进一步追踪到parseDefaultElement方法,可以看到这里就是识别主标签,从而进行解析生成bean。
/*
    根据标签去选择bean元素生成法
*/
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if(delegate.nodeNameEquals(ele, "import")) {
            this.importBeanDefinitionResource(ele);
        } else if(delegate.nodeNameEquals(ele, "alias")) {
            this.processAliasRegistration(ele);
        } else if(delegate.nodeNameEquals(ele, "bean")) {//找到啦,我们继续追踪这里。
            this.processBeanDefinition(ele, delegate);
        } else if(delegate.nodeNameEquals(ele, "beans")) {
            this.doRegisterBeanDefinitions(ele);
        }

    }
//进入解析和注册分发啦
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if(bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);

            try {
            //注册分发: 继续追踪
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
            } catch (BeanDefinitionStoreException var5) {
                this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
            }

            this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }

    }

    //终于找到你了,注册!!
    //BeanDefinitionReaderUtils类的
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
 //得到需要 注册 的 bean名字
        String beanName = definitionHolder.getBeanName();
         //开始注册。锁定registerBeanDefinition方法
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
         // 别名也是可以 通过IOC容器和bean联系起来的进行注册 
        String[] aliases = definitionHolder.getAliases();
        if(aliases != null) {
            String[] var4 = aliases;
            int var5 = aliases.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                String alias = var4[var6];
                registry.registerAlias(beanName, alias);
            }
        }

    }
    //锁定registerBeanDefinition方法后,然而我们发现的是一个接口BeanDefinitionRegistry,因此我们必须找到他的实现类,但是我们却只是发现很多他的抽象类AbstractAutowireCapableBeanFactory、AbstractBeanFactory、FactoryBeanRegistrySupport、DefaultSingletonBeanRegistry等等(感慨编写spring大佬的心累(我找得更累!!))

终于找到非抽象实现类啦:DefaultListableBeanFactory(其实我当时查的快疯,是查他的继承树才查到这个的。)

使用一个HashMap的集合对象存放IoC容器中注册解析的BeanDefinition

//~~~!!!实现了BeanDefinitionRegistry接口
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
//一堆验证beanDefinition的正确性
        Assert.hasText(beanName, "Bean name must not be empty");
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");
        if(beanDefinition instanceof AbstractBeanDefinition) {
            try {
                ((AbstractBeanDefinition)beanDefinition).validate();
            } catch (BeanDefinitionValidationException var4) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var4);
            }
        }
 //先看看在容器里是不是已经有了同名的bean,如果有抛出异常。
        BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
        if(oldBeanDefinition != null) {
            if(!this.isAllowBeanDefinitionOverriding()) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");
            }

            if(oldBeanDefinition.getRole() < beanDefinition.getRole()) {
                if(this.logger.isWarnEnabled()) {
                    this.logger.warn("Overriding user-define d bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
                }
            } else if(this.logger.isInfoEnabled()) {
                this.logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
            }
        } else {
        //没重复就把bean的名字加到IOC容器中去
            this.beanDefinitionNames.add(beanName);
            this.manualSingletonNames.remove(beanName);
            this.frozenBeanDefinitionNames = null;
        }
//这里把bean的名字和Bean定义联系起来放到一个HashMap中去,IOC容器通过这个Map来维护容器里的Bean定义信息。
        this.beanDefinitionMap.put(beanName, beanDefinition);
        if(oldBeanDefinition != null || this.containsSingleton(beanName)) {
            this.resetBeanDefinition(beanName);
        }

    }

总的来说就是:把beandefinition丢给工厂用hashmap存好。

IOC容器初始化总结

(1)通过setConfigLocations载入spring配置文件;

(2)初始化容器入口通过refresh方法,进入AbstractApplicationContext实现的refresh方法。

(3)然后通过obtainFreshBeanFactory方法进入子类AbstractRefreshableApplicationContext实现的refreshBeanFactory刷新一个容器工厂

(4)在此创建了DefaultListableBeanFactory类,并调用loadBeanDefinitions(beanFactory)装载bean定义

(5)接着以AbstractRefreshableApplicationContext为中心回到此类,进入其子类AbstractXmlApplicationContext实现的loadBeanDefinitions方法。对applicationContext.xml的解析操作,就是解析工厂的那个xml。

(6)再接着通过AbstractXmlApplicationContext的loadBeanDefinitions进入到AbstractBeanDefinitionReader类的loadBeanDefinitions。通过获取资源方法resourceLoader.getResource(location),获取到要加载的资源。再真正执行加载功能是其子类XmlBeanDefinitionReader实现的loadBeanDefinitions方法。

(6)接着进入XmlBeanDefinitionReader中的loadBeanDefinitions。(XmlBeanDefinitionReader通过调用其父类中调用的DefaultResourceLoader的getResource方法获取要加载的资源)DocumentLoader将Bean定义资源转换成Document对象。

(7)doLoadBeanDefinitions中进入DefaultBeanDefinitionDocumentReader类的registerBeanDefinitions 解 析 D ocument对象

(8)解析完后,调用DefaultListableBeanFactory类中使用一个HashMap的集合对象存放IoC容器中注册解析的BeanDefinition


2.IoC容器依赖注入过程:

[ 一 ]先来读懂beanfactory的继承逻辑树

类图。我们根据DefaultListableBeanFactory继续追踪上去。一会详讲此逻辑线。参考此博主此文章,非常感谢他,写得太棒了。让我学到很多。

这里写图片描述

先来读懂它beanfactory的继承树逻辑线。图取自此文章

这里写图片描述

解析上图:

BeanFactory是Spring的最根的接口,类的工厂接口。HierarchicalBeanFactory接口是在继承BeanFactory的基础上,实现BeanFactory的父子关系。Hierarchical表示的是这些 Bean 是有继承关系的,也就是每个 Bean 有可能有父 Bean。

AutowireCapableBeanFactory接口是在继承BeanFactory的基础上,实现Bean的自动装配功能。定义 Bean 的自动装配规则。

ListableBeanFactory接口是在继承BeanFactory的基础上,实现Bean的list集合操作功能。表示这些 Bean 是可列表的。

ConfigurableBeanFactory接口是在继承HierarchicalBeanFactory的基础上,实现BeanFactory的全部配置管理功能, SingletonBeanRegistry是单例bean的注册接口

ConfigurableListableBeanFactory接口是继承AutowireCapableBeanFactory,ListableBeanFactory,ConfigurableBeanFactory三个接口的一个综合接口。

AliasRegistry接口是别名注册接口,SimpleAliasRegistry类是简单的实现别名注册接口的类。

DefaultSingletonBeanRegistry是默认的实现SingletonBeanRegistry接口的类,同时,继承类SimpleAliasRegistry 。

FactoryBeanRegistrySupport是实现FactoryBean注册的功能实现。继承类DefaultSingletonBeanRegistry 。负责FactoryBean相关的操作,并缓存FactoryBean的getObject实例化的bean. 判断factory是单例,同时已经new好了单例时,先尝试去缓存找;如果找不到或者不是单例,委托doGetObjectFromFactoryBean实例化一个。

AbstractBeanFactory是部分实现接口ConfigurableBeanFactory,并继承类FactoryBeanRegistrySupport 。这个是最顶层的抽象IOC容器空构造器,主要用来具体实现了BeanFactory接口

AbstractAutowireCapableBeanFactory是实现接口AutowireCapableBeanFactory,并继承类 AbstractBeanFactory 。主要的功能就是实现了默认的bean创建方法createBean().而在这个创建过程中,提供了诸如bean的属性注入,初始化方法的调用,自动装配的实现,bean处理器的调用。

DefaultListableBeanFactory实现接口 ConfigurableListableBeanFactory、BeanDefinitionRegistry(bean定义的注册接口), 并继承AbstractAutowireCapableBeanFactory,实现全部类管理的功能。

可以看出DefaultListableBeanFactory就是springIoC机制的入口。


[二]IoC容器依赖注入源码详讲:上面可知我们从实现BeanFactory的AbstractBeanFactory入手

1.我们从DefaultListableBeanFactory开始不断追踪父类,直到找到了AbstractBeanFactory。

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
//真正实现向IoC容器获取Bean的功能,也是触发依赖注入功能的地方  
    protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
    //根据指定的名称获取被管理Bean的名称,剥离指定名称中对容器的相关依赖  
       //如果指定的是别名,将别名转换为规范的Bean名称  
        final String beanName = this.transformedBeanName(name);
        Object sharedInstance = this.getSingleton(beanName);
        Object bean;
         //IoC容器创建单态模式Bean实例对象  
        if(sharedInstance != null && args == null) {
            if(this.logger.isDebugEnabled()) {
            //如果指定名称的Bean在容器中已有单态模式的Bean被创建,直接返回  
               //已经有创建的Bean 
                if(this.isSingletonCurrentlyInCreation(beanName)) {
                    this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
                } else {
                    this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            //获取给定Bean的实例对象,主要是完成FactoryBean的相关处理  
           //注意:BeanFactory是管理容器中Bean的工厂,而FactoryBean是  
           //创建创建对象的工厂Bean,两者之间有区别  
            bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
        } else {
        //缓存没有正在创建的单态模式Bean  
           //缓存中已经有已经创建的原型模式Bean,但是由于循环引用的问题导致实  
           //例化对象失败 
            if(this.isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
            //对IoC容器中是否存在指定名称的BeanDefinition进行检查,首先检查是否  
           //能在当前的BeanFactory中获取的所需要的Bean,如果不能则委托当前容器  
           //的父级容器去查找,如果还是找不到则沿着容器的继承体系向父级容器查找
            BeanFactory parentBeanFactory = this.getParentBeanFactory();
            //当前容器的父级容器存在,且当前容器中不存在指定名称的Bean  
            if(parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
             //解析指定Bean名称的原始名称 
                String nameToLookup = this.originalBeanName(name);
                if(args != null) {
                //委派父级容器根据指定名称和显式的参数查找 
                    return parentBeanFactory.getBean(nameToLookup, args);
                }
                    //委派父级容器根据指定名称和类型查找
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
          //创建的Bean是否需要进行类型验证,一般不需要  
            if(!typeCheckOnly) {
            //向容器标记指定的Bean已经被创建 
                this.markBeanAsCreated(beanName);
            }

            try {
             //根据指定Bean名称获取其父级的Bean定义,主要解决Bean继承时子类  
           //合并父类公共属性问题 
                final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                this.checkMergedBeanDefinition(mbd, beanName, args);
                 //获取当前Bean所有依赖Bean的名称 
                String[] dependsOn = mbd.getDependsOn();
                String[] var11;//用来暂存dependsOn ,用var11来循环
                //如果当前Bean有依赖Bean 
                if(dependsOn != null) {
                    var11 = dependsOn;
                    int var12 = dependsOn.length;
                    
                    for(int var13 = 0; var13 < var12; ++var13) {
                     //递归调用getBean方法,获取当前Bean的依赖Bean  
                        String dependsOnBean = var11[var13];
                        if(this.isDependent(beanName, dependsOnBean)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
                        }
                     //把被依赖Bean注册给当前依赖的Bean  
                        this.registerDependentBean(dependsOnBean, beanName);
                        this.getBean(dependsOnBean);
                    }
                }
         //创建单态模式Bean的实例对象 
                if(mbd.isSingleton()) {
                //这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象  
                    sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
                        public Object getObject() throws BeansException {
                            try {
                             //创建一个指定Bean实例对象,如果有父级继承,则合并子类和父类的定义!!!!!就是在此再次分发到创建bean的实现方法
                                return AbstractBeanFactory.this.createBean(beanName, mbd, args);
                            } catch (BeansException var2) {
                             //显式地从容器单态模式Bean缓存中清除实例对象  
                                AbstractBeanFactory.this.destroySingleton(beanName);
                                throw var2;
                            }
                        }
                    });
                    //获取给定Bean的实例对象  
                    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                } else if(mbd.isPrototype()) { //IoC容器创建原型模式Bean实例对象  
                    var11 = null;

                    Object prototypeInstance;//原型模式(Prototype)是每次都会创建一个新的对象 
                    try {
                    //回调beforePrototypeCreation方法,默认的功能是注册当前创//建的原型对象  
                        this.beforePrototypeCreation(beanName);
                         //创建指定Bean对象实例  
                        prototypeInstance = this.createBean(beanName, mbd, args);
                    } finally {
                  //回调afterPrototypeCreation方法,默认的功能告诉IoC容器指//定Bean的原型对象不再创建了
                        this.afterPrototypeCreation(beanName);
                    }
                //获取给定Bean的实例对象  
                    bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                } else {
           //要创建的Bean既不是单态模式,也不是原型模式,则根据Bean定义资源中  
           //配置的生命周期范围,选择实例化Bean的合适方法,这种在Web应用程序中  
           //比较常用,如:request、session、application等生命周期
                    String scopeName = mbd.getScope();
                    Scope scope = (Scope)this.scopes.get(scopeName);
                    //Bean定义资源中没有配置生命周期范围,则Bean定义不合法
                    if(scope == null) {
                        throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
                    }

                    try {
                     //这里又使用了一个匿名内部类,获取一个指定生命周期范围的实例
                        Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                            public Object getObject() throws BeansException {
                                AbstractBeanFactory.this.beforePrototypeCreation(beanName);

                                Object var1;
                                try {
                                    var1 = AbstractBeanFactory.this.createBean(beanName, mbd, args);
                                } finally {
                                    AbstractBeanFactory.this.afterPrototypeCreation(beanName);
                                }

                                return var1;
                            }
                        });
                         //获取给定Bean的实例对象  
                        bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    } catch (IllegalStateException var21) {
                        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", var21);
                    }
                }
            } catch (BeansException var23) {
                this.cleanupAfterBeanCreationFailure(beanName);
                throw var23;
            }
        }
 //对创建的Bean实例对象进行类型检查  
        if(requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
            try {
                return this.getTypeConverter().convertIfNecessary(bean, requiredType);
            } catch (TypeMismatchException var22) {
                if(this.logger.isDebugEnabled()) {
                    this.logger.debug("Failed to convert bean '" + name + "' to required type [" + ClassUtils.getQualifiedName(requiredType) + "]", var22);
                }

                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        } else {
            return bean;
        }
    }
}

我们可以很清晰看到,创建bean的时候所做的判断:

(1)如果Bean定义的单态模式(Singleton),则容器在创建之前先从缓存中查找,以确保整个容器中只存在一个实例对象

(2) 如果Bean定义的是原型模式(Prototype),则容器每次都会创建一个新的实例对象。

(3)两者都不是,则根据Bean定义资源中配置的生命周期范围,选择实例化Bean的合适方法,这种在Web应用程序中 比较常用,如:request、session、application等生命周期。

上面的源码只是定义了根据Bean定义的模式,采取的不同创建Bean实例对象的策略,具体的Bean实例对象的创建过程由实现了ObejctFactory接口的匿名内部类的createBean方法完成,ObejctFactory使用委派模式,具体的Bean实例创建过程交由其实现类AbstractAutowireCapableBeanFactory完成,我们继续分析AbstractAutowireCapableBeanFactory的createBean方法的源码,理解其创建Bean实例的具体实现过程

2.因此我们根据上面所述继续追踪,现追踪AbstractBeanFactory的一个匿名内部类的createBean方法,实际上这方法的实现就是在我们从DefaultListableBeanFactory追踪父类过来的途中遇到的AbstractAutowireCapableBeanFactory类,是AbstractBeanFactory子类。

//创建Bean实 例对象  
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Creating instance of bean '" + beanName + "'");
        }
//判断需要创建的Bean是否可以实例化,即是否可以通过当前的类加载器加载  
        this.resolveBeanClass(mbd, beanName, new Class[0]);
//校验和准备Bean中的方法覆盖 
        try {
            mbd.prepareMethodOverrides();
        } catch (BeanDefinitionValidationException var5) {
            throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "Validation of method overrides failed", var5);
        }

        Object beanInstance;
        try {
        //如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建
        //Bean的代理对象
            beanInstance = this.resolveBeforeInstantiation(beanName, mbd);
            if(beanInstance != null) {
                return beanInstance;
            }
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var6);
        }
//真正创建Bean的入口  
        beanInstance = this.doCreateBean(beanName, mbd, args);
        if(this.logger.isDebugEnabled()) {
            this.logger.debug("Finished creating instance of bean '" + beanName + "'");
        }

        return beanInstance;
    }
//真正创建bean的方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) {
//封装被创建的Bean对象  
        BeanWrapper instanceWrapper = null;
        if(mbd.isSingleton()) {//单态模式的Bean,先从容器中缓存中获取同名Bean
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }
        //容器没有的话
        if(instanceWrapper == null) {
         //创建实例对象  
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }

        final Object bean = instanceWrapper != null?instanceWrapper.getWrappedInstance():null;
        //获取实例化对象的类型  
        Class<?> beanType = instanceWrapper != null?instanceWrapper.getWrappedClass():null;
        Object var7 = mbd.postProcessingLock;
        //调用PostProcessor后置处理器  
        synchronized(mbd.postProcessingLock) {
            if(!mbd.postProcessed) {
                this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                mbd.postProcessed = true;
            }
        }
 //向容器中缓存单态模式的Bean对象,以防循环引用  
        boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if(earlySingletonExposure) {
            if(this.logger.isDebugEnabled()) {
                this.logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }
 //这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用  
            this.addSingletonFactory(beanName, new ObjectFactory<Object>() {
                public Object getObject() throws BeansException {
                    return AbstractAutowireCapableBeanFactory.this.getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }
         //Bean对象的初始化,依赖注入在此触发  
       //这个exposedObject在初始化完成之后返回作为依赖注入完成后的Bean 
        Object exposedObject = bean;
        try {
        //将Bean实例对象封装,并且Bean定义中配置的属性值赋值给实例对象
            this.populateBean(beanName, mbd, instanceWrapper);
            if(exposedObject != null) {
            //初始化Bean对象  
                exposedObject = this.initializeBean(beanName, exposedObject, mbd);
            }
        } catch (Throwable var17) {
            if(var17 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var17).getBeanName())) {
                throw (BeanCreationException)var17;
            }

            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var17);
        }

        if(earlySingletonExposure) {
         //获取指定名称的已注册的单态模式Bean对象  
            Object earlySingletonReference = this.getSingleton(beanName, false);
            if(earlySingletonReference != null) {
             //根据名称获取的以注册的Bean和正在实例化的Bean是同一个  
                if(exposedObject == bean) {
                //当前实例化的Bean初始化完成  
                    exposedObject = earlySingletonReference;
                } else if(!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {//当前Bean依赖其他Bean,并且当发生循环引用时不允许新创建实例对象 
                    String[] dependentBeans = this.getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                    String[] var12 = dependentBeans;//用来暂存当前bean
                    int var13 = dependentBeans.length;
            //获取当前Bean所依赖的其他Bean 
                    for(int var14 = 0; var14 < var13; ++var14) {
                        String dependentBean = var12[var14];
                        //对依赖Bean进行类型检查  
                        if(!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }

                    if(!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }
        //注册完成依赖注入的Bean  
        try {
            this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
            return exposedObject;
        } catch (BeanDefinitionValidationException var16) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
        }
    }

上面还是一堆校验以及状态判断。

其中真正实现是分发到:

createBeanInstance:生成Bean所包含的Java对象实例。
populateBean :对Bean属性的依赖注入进行处理。

3.那么我们来看下createBeanInstance方法的代码,还是在AbstractAutowireCapableBeanFactory类中。

在此方法中,根据指定的初始化策略,使用静态工厂、工厂方法或者容器的自动装配特性生成java实例对象。

//创建Bean的实例对象  
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
  //检查确认Bean是可实例化的  
        Class<?> beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
        //使用工厂方法对Bean进行实例化  
        if(beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
        } else if(mbd.getFactoryMethodName() != null) {
        //调用工厂方法实例化  
            return this.instantiateUsingFactoryMethod(beanName, mbd, args);
        } else { //使用容器的自动装配方法进行实例化 
            boolean resolved = false;
            boolean autowireNecessary = false;
            if(args == null) {
                Object var7 = mbd.constructorArgumentLock;
                synchronized(mbd.constructorArgumentLock) {
                    if(mbd.resolvedConstructorOrFactoryMethod != null) {
                        resolved = true;
                        //决定是否使用自动装配的构造器
                        autowireNecessary = mbd.constructorArgumentsResolved;
                    }
                }
            }
        //autowireConstructor构造器方法配置了自动装配属性,使用容器的自动装配实例化,容器的自动装配是根据参数类型匹配Bean的构造方法
            if(resolved) {
               //根据标记位autowireNecessary而决定采用无参构造器还是自动装配构造器
                return autowireNecessary?this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null):this.instantiateBean(beanName, mbd);
            } else {
               //使用Bean的构造方法进行实例化
                Constructor<?>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
               //根据是否有参数还是已经配置了自动装配模式,去选择构造器,无参构造器还是自动装配构造器。
                return ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args)?this.instantiateBean(beanName, mbd):this.autowireConstructor(beanName, mbd, ctors, args);
            }
        }
    }

上面看到一个无参构造器:instantiateBean

 //使用默认的无参构造方法实例化Bean对象  
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
        try {
            Object beanInstance;
            //获取系统的安全管理接口,JDK标准的安全管理API  
            if(System.getSecurityManager() != null) {
             //这里是一个匿名内置类,根据实例化策略创建实例对象 
                beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    public Object run() {
                        return AbstractAutowireCapableBeanFactory.this.getInstantiationStrategy().instantiate(mbd, beanName, AbstractAutowireCapableBeanFactory.this);
                    }
                }, this.getAccessControlContext());
            } else {
            //将实例化的对象封装起来
                beanInstance = this.getInstantiationStrategy().instantiate(mbd, beanName, this);
            }

            BeanWrapper bw = new BeanWrapperImpl(beanInstance);
            this.initBeanWrapper(bw);
            return bw;
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", var6);
        }
    }

4.我们都看到了,无论什么调用什么构造器,返回的都是统一的BeanWrapper

BeanWrapper是什么贵?org.springframework.beans.BeanWrapper是Spring框架中重要的组件类。BeanWrapper相当于一个代理器,Spring通过BeanWrapper完成Bean属性的填充工作。在Bean实例被InstantiationStrategy创建出来之后,容器主控程序将Bean实例通过BeanWrapper包装起来。

由于它是接口,必然有个实现类,实现依赖注入的具体实现。那就是BeanWrapperImpl,它的作用是:(1)Bean包裹器;(2)属性访问器;(3)属性编辑器注册表。

5.我们接着回到createBean,它还有个实现分发populateBean 方法:对Bean属性的依赖注入进行处理

过程是两部分:属性值解析和注入

//将Bean属性设置到生成的实例对象上 
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    //获取容器在解析Bean定义资源时为BeanDefiniton中设置的属性值
        PropertyValues pvs = mbd.getPropertyValues();
        //实例对象为null 
        if(bw == null) {
         //属性值不为空  
            if(!((PropertyValues)pvs).isEmpty()) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
            }
        } else {
         //在设置属性之前调用Bean的PostProcessor后置处理器  
            boolean continueWithPropertyPopulation = true;
            if(!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
                Iterator var6 = this.getBeanPostProcessors().iterator();

                while(var6.hasNext()) {
                    BeanPostProcessor bp = (BeanPostProcessor)var6.next();
                    if(bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                        if(!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                            continueWithPropertyPopulation = false;
                            break;
                        }
                    }
                }
            }
        //依赖注入开始,首先处理autowire自动装配的注入  
            if(continueWithPropertyPopulation) {
                if(mbd.getResolvedAutowireMode() == 1 || mbd.getResolvedAutowireMode() == 2) {
                    MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
                     //对autowire自动装配的处理,根据Bean名称自动装配注入  
                    if(mbd.getResolvedAutowireMode() == 1) {
                        this.autowireByName(beanName, mbd, bw, newPvs);
                    }
                     //根据Bean类型自动装配注入 
                    if(mbd.getResolvedAutowireMode() == 2) {
                        this.autowireByType(beanName, mbd, bw, newPvs);
                    }

                    pvs = newPvs;
                }
            //检查容器是否持有用于处理单态模式Bean关闭时的后置处理器 
                boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
              //Bean实例对象没有依赖,即没有继承基类 
                boolean needsDepCheck = mbd.getDependencyCheck() != 0;
                if(hasInstAwareBpps || needsDepCheck) {
                //从实例对象中提取属性描述符  
                    PropertyDescriptor[] filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                    if(hasInstAwareBpps) {
                        Iterator var9 = this.getBeanPostProcessors().iterator();

                        while(var9.hasNext()) {
                            BeanPostProcessor bp = (BeanPostProcessor)var9.next();
                            if(bp instanceof InstantiationAwareBeanPostProcessor) {
                                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                                //使用BeanPostProcessor处理器处理属性值  
                                pvs = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
                                if(pvs == null) {
                                    return;
                                }
                            }
                        }
                    }

                    if(needsDepCheck) {
                    //为要设置的属性进行依赖检查  
                        this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
                    }
                }
              //对属性进行注入  ,解析并注入依赖属性的过程  就在这个方法里面
              /*
              属性转换也有两情况:
              1.属性值类型不需要转换时,不需要解析属性值,直接准备进行依赖注入。
              2.属性值需要进行类型转换时,如对其他对象的引用等,首先需要解析属性值,然后对解析后的属性值进行依赖注入。
              */
                this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
            }
        }
    }

6.那么我们继续追踪applyPropertyValues方法

//解析并注入依赖属性的过程 
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
        if(pvs != null && !pvs.isEmpty()) {
         //封装属性值
            MutablePropertyValues mpvs = null;
            if(System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
             //设置安全上下文,JDK安全机制  
                ((BeanWrapperImpl)bw).setSecurityContext(this.getAccessControlContext());
            }

            List original;
            if(pvs instanceof MutablePropertyValues) {           
                mpvs = (MutablePropertyValues)pvs;
                 //属性值已经转换  
                if(mpvs.isConverted()) {
                    try {
                     //为实例化对象设置属性值 ,依赖注入真真正正地实现在此!!!!!
                        bw.setPropertyValues(mpvs);
                        return;
                    } catch (BeansException var18) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", var18);
                    }
                }
             //获取属性值对象的原始类型值  
                original = mpvs.getPropertyValueList();
            } else {
                original = Arrays.asList(pvs.getPropertyValues());
            }
            //获取用户自定义的类型转换  
            TypeConverter converter = this.getCustomTypeConverter();
            if(converter == null) {
                converter = bw;
            }
        //创建一个Bean定义属性值解析器,将Bean定义中的属性值解析为Bean实例对象  
       //的实际值
            BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, (TypeConverter)converter);
             //为属性的解析值创建一个拷贝,将拷贝的数据注入到实例对象中  
            List<PropertyValue> deepCopy = new ArrayList(original.size());
            boolean resolveNecessary = false;
            Iterator var11 = original.iterator();//用迭代器去遍历

            while(true) {
                while(var11.hasNext()) {
                    PropertyValue pv = (PropertyValue)var11.next();
                     //属性值不需要转换  
                    if(pv.isConverted()) {
                        deepCopy.add(pv);
                    } else {//属性值需要转换 
                        String propertyName = pv.getName();
                        //原始的属性值,即转换之前的属性值  
                        Object originalValue = pv.getValue();
                          //转换属性值,例如将引用转换为IoC容器中实例化对象引用 !!!!! 对属性值的解析!!
                        Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
                        //转换之后的属性值 
                        Object convertedValue = resolvedValue;
                         //属性值是否可以转换  
                        boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
                        if(convertible) {
                         //使用用户自定义的类型转换器转换属性值  
                            convertedValue = this.convertForProperty(resolvedValue, propertyName, bw, (TypeConverter)converter);
                        }
                //存储转换后的属性值,避免每次属性注入时的转换工作
                        if(resolvedValue == originalValue) {
                            if(convertible) {
                             //设置属性转换之后的值
                                pv.setConvertedValue(convertedValue);
                            }

                            deepCopy.add(pv);
                        } 
                             //属性是可转换的,且属性原始值是字符串类型,且属性的原始类型值不是  
               //动态生成的字符串,且属性的原始值不是集合或者数组类型
                            else if(convertible && originalValue instanceof TypedStringValue && !((TypedStringValue)originalValue).isDynamic() && !(convertedValue instanceof Collection) && !ObjectUtils.isArray(convertedValue)) {
                            pv.setConvertedValue(convertedValue);
                            deepCopy.add(pv);
                        } else {
                            resolveNecessary = true;
                            //重新封装属性的值  
                            deepCopy.add(new PropertyValue(pv, convertedValue));
                        }
                    }
                }

                if(mpvs != null && !resolveNecessary) {
                 //标记属性值已经转换过  
                    mpvs.setConverted();
                }
                //进行属性依赖注入  ,依赖注入的真真正正实现依赖的注入方法在此!!!
                try {
                    bw.setPropertyValues(new MutablePropertyValues(deepCopy));
                    return;
                } catch (BeansException var19) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", var19);
                }
            }
        }
    }

总结applyPropertyValues方法(完成属性转换):

属性值类型不需要转换时,不需要解析属性值,直接准备进行依赖注入。

属性值需要进行类型转换时,如对其他对象的引用等,首先需要解析属性值,然后对解析后的属性值进行依赖注入。

而且我们看到调用了resolveValueIfNecessary方法对属性值的解析

7.追踪resolveValueIfNecessary,发现是在BeanDefinitionValueResolver类

当容器在对属性进行依赖注入时,如果发现属性值需要进行类型转换,如属性值是容器中另一个Bean实例对象的引用,则容器首先需要根据属性值解析出所引用的对象,然后才能将该引用对象注入到目标实例对象的属性上去,对属性进行解析的由resolveValueIfNecessary方法实现。

可知:创建与注入是个递归的过程

//解析属性值,对注入类型进行转换 
public Object resolveValueIfNecessary(Object argName, Object value) {
//对引用类型的属性进行解析
        if(value instanceof RuntimeBeanReference) {
            RuntimeBeanReference ref = (RuntimeBeanReference)value;
            //调用引用类型属性的解析方法  
            return this.resolveReference(argName, ref);
        } else if(value instanceof RuntimeBeanNameReference) { //对属性值是引用容器中另一个Bean名称的解析  
            String refName = ((RuntimeBeanNameReference)value).getBeanName();
            refName = String.valueOf(this.doEvaluate(refName));
             //从容器中获取指定名称的Bean 
            if(!this.beanFactory.containsBean(refName)) {
                throw new BeanDefinitionStoreException("Invalid bean name '" + refName + "' in bean reference for " + argName);
            } else {
                return refName;
            }
        } else if(value instanceof BeanDefinitionHolder) { //对Bean类型属性的解析,主要是Bean中的内部类  
            BeanDefinitionHolder bdHolder = (BeanDefinitionHolder)value;
            return this.resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
        } else if(value instanceof BeanDefinition) {
            BeanDefinition bd = (BeanDefinition)value;
            String innerBeanName = "(inner bean)#" + ObjectUtils.getIdentityHexString(bd);
            return this.resolveInnerBean(argName, innerBeanName, bd);
        } else if(value instanceof ManagedArray) {//对集合数组类型的属性解析 
            ManagedArray array = (ManagedArray)value;
              //获取数组的类型  
            Class<?> elementType = array.resolvedElementType;
            if(elementType == null) {
            //获取数组元素的类型  
                String elementTypeName = array.getElementTypeName();
                if(StringUtils.hasText(elementTypeName)) {
                    try {
                    //使用反射机制创建指定类型的对象  
                        elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
                        array.resolvedElementType = elementType;
                    } catch (Throwable var9) {
                        throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Error resolving array type for " + argName, var9);
                    }
                } else {
                //没有获取到数组的类型,也没有获取到数组元素的类型,则直接设置数  
               //组的类型为Object 
                    elementType = Object.class;
                }
            }
             //创建指定类型的数组  
            return this.resolveManagedArray(argName, (List)value, elementType);
        } else if(value instanceof ManagedList) {//解析list类型的属性值  
            return this.resolveManagedList(argName, (List)value);
        } else if(value instanceof ManagedSet) { //解析set类型的属性值 
            return this.resolveManagedSet(argName, (Set)value);
        } else if(value instanceof ManagedMap) { //解析map类型的属性值 
            return this.resolveManagedMap(argName, (Map)value);
        } else if(value instanceof ManagedProperties) { //解析props类型的属性值,props其实就是key和value均为字符串的map  
            Properties original = (Properties)value;
            //创建一个拷贝,用于作为解析后的返回值  
            Properties copy = new Properties();

            Object propKey;
            Object propValue;
            for(Iterator var19 = original.entrySet().iterator(); var19.hasNext(); copy.put(propKey, propValue)) {
                Entry<Object, Object> propEntry = (Entry)var19.next();
                propKey = propEntry.getKey();
                propValue = propEntry.getValue();
                if(propKey instanceof TypedStringValue) {
                    propKey = this.evaluate((TypedStringValue)propKey);
                }

                if(propValue instanceof TypedStringValue) {
                    propValue = this.evaluate((TypedStringValue)propValue);
                }
            }

            return copy;
        } else if(value instanceof TypedStringValue) {//解析字符串类型的属性值  
            TypedStringValue typedStringValue = (TypedStringValue)value;
            Object valueObject = this.evaluate(typedStringValue);

            try {
            //获取属性的目标类型  
                Class<?> resolvedTargetType = this.resolveTargetType(typedStringValue);
                 //对目标类型的属性进行解析,递归调用 。没有获取到属性的目标对象,则按Object类型返回  
                return resolvedTargetType != null?this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType):valueObject;
            } catch (Throwable var10) {
                throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Error converting typed String value for " + argName, var10);
            }
        } else {
            return this.evaluate(value);
        }
    }

刚也说了解析引用类型是特殊的:resolveReference方法

   //解析引用类型的属性值  
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
        try {
          //获取引用的Bean名称  
            String refName = ref.getBeanName();
            refName = String.valueOf(this.doEvaluate(refName));
            //如果引用的对象在父类容器中,则从父类容器中获取指定的引用对象  
            if(ref.isToParent()) {
                if(this.beanFactory.getParentBeanFactory() == null) {
                    throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Can't resolve reference to bean '" + refName + "' in parent factory: no parent factory available");
                } else {
                    return this.beanFactory.getParentBeanFactory().getBean(refName);
                }
            } else {
             //从当前的容器中获取指定的引用Bean对象,如果指定的Bean没有被实例化  
           //则会递归触发引用Bean的初始化和依赖注入  
                Object bean = this.beanFactory.getBean(refName);
                //将当前实例化对象的依赖引用对象  
                this.beanFactory.registerDependentBean(refName, this.beanName);
                return bean;
            }
        } catch (BeansException var5) {
            throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, var5);
        }
    }

8.并且我们注意到applyPropertyValues方法(刚刚的AbstractAutowireCapableBeanFactory类)中,分发了一个方法实现对属性值的依赖注入setPropertyValues

前面也说到BeanWrapper接口的实现类就是BeanWrapperImpl。一系列的依赖注入都在这个里面,那么我们往上查找PropertyAccessor接口,并且发现路过的抽象类AbstractPropertyAccessor,终于找到了setPropertyValues方法的实现,有个模板模式,就是调用在AbstractPropertyAccessor中的抽象方法setPropertyValue(此方法在BeanWrapperImpl实现了!!)

//实现属性依赖注入功能
private void setPropertyValue(BeanWrapperImpl.PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
 //PropertyTokenHolder主要保存属性的名称、路径,以及集合的size等信息
        String propertyName = tokens.canonicalName;
        String actualName = tokens.actualName;
        Object propValue;
        //keys是用来保存集合类型属性的size  
        if(tokens.keys != null) {
         //将属性信息拷贝
            BeanWrapperImpl.PropertyTokenHolder getterTokens = new BeanWrapperImpl.PropertyTokenHolder(null);
            getterTokens.canonicalName = tokens.canonicalName;
            getterTokens.actualName = tokens.actualName;
            getterTokens.keys = new String[tokens.keys.length - 1];
            System.arraycopy(tokens.keys, 0, getterTokens.keys, 0, tokens.keys.length - 1);

            try {
             //获取属性值,该方法内部使用JDK的内省( Introspector)机制,调用属性//的getter(readerMethod)方法,获取属性的值  
                propValue = this.getPropertyValue(getterTokens);
            } catch (NotReadablePropertyException var21) {
                throw new NotWritablePropertyException(this.getRootClass(), this.nestedPath + propertyName, "Cannot access indexed value in property referenced in indexed property path '" + propertyName + "'", var21);
            }
            //获取集合类型属性的长度  
            String key = tokens.keys[tokens.keys.length - 1];
            if(propValue == null) {
                if(!this.isAutoGrowNestedPaths()) {
                    throw new NullValueInNestedPathException(this.getRootClass(), this.nestedPath + propertyName, "Cannot access indexed value in property referenced in indexed property path '" + propertyName + "': returned null");
                }

                int lastKeyIndex = tokens.canonicalName.lastIndexOf(91);
                getterTokens.canonicalName = tokens.canonicalName.substring(0, lastKeyIndex);
                propValue = this.setDefaultValue(getterTokens);
            }

            Object convertedValue;
            Object newArray;
            Class requiredType;
            PropertyDescriptor pd;
            //注入array类型的属性值 
            if(propValue.getClass().isArray()) {
            //获取属性的描述符  
                pd = this.getCachedIntrospectionResults().getPropertyDescriptor(actualName);
                 //获取数组的类型 
                requiredType = propValue.getClass().getComponentType();
                //获取数组的长度  
                int arrayIndex = Integer.parseInt(key);
                Object oldValue = null;

                try {
                //获取数组以前初始化的值  
                    if(this.isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
                        oldValue = Array.get(propValue, arrayIndex);
                    }
                //将属性的值赋值给数组中的元素
                    convertedValue = this.convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType, TypeDescriptor.nested(this.property(pd), tokens.keys.length));
                    int length = Array.getLength(propValue);
                    if(arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {
                        Class<?> componentType = propValue.getClass().getComponentType();
                        newArray = Array.newInstance(componentType, arrayIndex + 1);
                        System.arraycopy(propValue, 0, newArray, 0, length);
                        this.setPropertyValue(actualName, newArray);
                        propValue = this.getPropertyValue(actualName);
                    }

                    Array.set(propValue, arrayIndex, convertedValue);
                } catch (IndexOutOfBoundsException var20) {
                    throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + propertyName, "Invalid array index in property path '" + propertyName + "'", var20);
                }
            } else {
                Object convertedValue;
                if(propValue instanceof List) {//注入list类型的属性值
                    pd = this.getCachedIntrospectionResults().getPropertyDescriptor(actualName);
                     //获取list集合的类型 
                    requiredType = GenericCollectionTypeResolver.getCollectionReturnType(pd.getReadMethod(), tokens.keys.length);
                    List<Object> list = (List)propValue;
                    //获取list集合的size
                    int index = Integer.parseInt(key);
                    convertedValue = null;
                    if(this.isExtractOldValueForEditor() && index < list.size()) {
                        convertedValue = list.get(index);
                    }
                     //获取list解析后的属性值  
                    convertedValue = this.convertIfNecessary(propertyName, convertedValue, pv.getValue(), requiredType, TypeDescriptor.nested(this.property(pd), tokens.keys.length));
                    int size = list.size();
                     //如果list的长度大于属性值的长度,则多余的元素赋值为null  
                    if(index >= size && index < this.autoGrowCollectionLimit) {
                        for(int i = size; i < index; ++i) {
                            try {//如果list的长度大于属性值的长度,则多余的元素赋值为null  
                                list.add((Object)null);
                            } catch (NullPointerException var19) {
                                throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + propertyName, "Cannot set element with index " + index + " in List of size " + size + ", accessed using property path '" + propertyName + "': List does not support filling up gaps with null elements");
                            }
                        }

                        list.add(convertedValue);
                    } else {  //如果list的长度小于属性值的长度,为list属性赋值  
                        try {
                            list.set(index, convertedValue);
                        } catch (IndexOutOfBoundsException var18) {
                            throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + propertyName, "Invalid list index in property path '" + propertyName + "'", var18);
                        }
                    }
                } else {  //注入map类型的属性值  
                    if(!(propValue instanceof Map)) {
                        throw new InvalidPropertyException(this.getRootClass(), this.nestedPath + propertyName, "Property referenced in indexed property path '" + propertyName + "' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
                    }

                    pd = this.getCachedIntrospectionResults().getPropertyDescriptor(actualName);
                  //获取map集合key的类型 
                    requiredType = GenericCollectionTypeResolver.getMapKeyReturnType(pd.getReadMethod(), tokens.keys.length);
                      //获取map集合value的类型
                    Class<?> mapValueType = GenericCollectionTypeResolver.getMapValueReturnType(pd.getReadMethod(), tokens.keys.length);
                    Map<Object, Object> map = (Map)propValue;//强转
                     //解析map类型属性key值  
                    TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(requiredType);
                      //解析map类型属性value值 
                    convertedValue = this.convertIfNecessary((String)null, (Object)null, key, requiredType, typeDescriptor);
                    Object oldValue = null;
                    if(this.isExtractOldValueForEditor()) {
                        oldValue = map.get(convertedValue);
                    }

                    newArray = this.convertIfNecessary(propertyName, oldValue, pv.getValue(), mapValueType, TypeDescriptor.nested(this.property(pd), tokens.keys.length));
                    //将解析后的key和value值赋值给map集合属性
                    map.put(convertedValue, newArray);
                }
            }
        } else { //对非集合类型的属性注入 
            PropertyDescriptor pd = pv.resolvedDescriptor;
            if(pd == null || !pd.getWriteMethod().getDeclaringClass().isInstance(this.object)) {
                pd = this.getCachedIntrospectionResults().getPropertyDescriptor(actualName);
                 //无法获取到属性名或者属性没有提供setter(写方法)方法 
                if(pd == null || pd.getWriteMethod() == null) {
                 //如果属性值是可选的,即不是必须的,则忽略该属性值  
                    if(pv.isOptional()) {
                        logger.debug("Ignoring optional value for property '" + actualName + "' - property not found on bean class [" + this.getRootClass().getName() + "]");
                        return;
                    }
      //如果属性值是必须的,则抛出无法给属性赋值,因为每天提供setter方法异常  
                    PropertyMatches matches = PropertyMatches.forProperty(propertyName, this.getRootClass());
                    throw new NotWritablePropertyException(this.getRootClass(), this.nestedPath + propertyName, matches.buildErrorMessage(), matches.getPossibleMatches());
                }

                pv.getOriginalPropertyValue().resolvedDescriptor = pd;
            }

            propValue = null;

            PropertyChangeEvent propertyChangeEvent;
            try {
                Object originalValue = pv.getValue();//拿到初始值
                Object valueToApply = originalValue;
                final Method readMethod;
                if(!Boolean.FALSE.equals(pv.conversionNecessary)) {
                    if(pv.isConverted()) {
                        valueToApply = pv.getConvertedValue();
                    } else {
                        if(this.isExtractOldValueForEditor() && pd.getReadMethod() != null) {
                          //获取属性的getter方法(读方法),JDK内省机制
                            readMethod = pd.getReadMethod();
                            //如果属性的getter方法不是public访问控制权限的,即访问控制权限比较严格,  
                           //则使用JDK的反射机制强行访问非public的方法(暴力读取属性值)
                          if(!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) && !readMethod.isAccessible()) {
                                if(System.getSecurityManager() != null) {
                                //匿名内部类,根据权限修改属性的读取控制限制  
                                    AccessController.doPrivileged(new PrivilegedAction<Object>() {
                                        public Object run() {
                                            readMethod.setAccessible(true);
                                            return null;
                                        }
                                    });
                                } else {
                                    readMethod.setAccessible(true);
                                }
                            }

                            try {
                            //属性没有提供getter方法时,调用潜在的读取属性值//的方法,获取属性值  
                                if(System.getSecurityManager() != null) {
                                    propValue = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                                        public Object run() throws Exception {
                                            return readMethod.invoke(BeanWrapperImpl.this.object, new Object[0]);
                                        }
                                    }, this.acc);
                                } else {
                                    propValue = readMethod.invoke(this.object, new Object[0]);
                                }
                            } catch (Exception var22) {
                                Exception ex = var22;
                                if(var22 instanceof PrivilegedActionException) {
                                    ex = ((PrivilegedActionException)var22).getException();
                                }

                                if(logger.isDebugEnabled()) {
                                    logger.debug("Could not read previous value of property '" + this.nestedPath + propertyName + "'", ex);
                                }
                            }
                        }
                 //设置属性的注入值  
                        valueToApply = this.convertForProperty(propertyName, propValue, originalValue, new TypeDescriptor(this.property(pd)));
                    }

                    pv.getOriginalPropertyValue().conversionNecessary = Boolean.valueOf(valueToApply != originalValue);
                }
             //根据JDK的内省机制,获取属性的setter(写方法)方法 
                readMethod = pd instanceof GenericTypeAwarePropertyDescriptor?((GenericTypeAwarePropertyDescriptor)pd).getWriteMethodForActualAccess():pd.getWriteMethod();
                //如果属性的setter方法是非public,即访问控制权限比较严格,则使用JDK的反射机制,  
               //强行设置setter方法可访问(暴力为属性赋值) 
                if(!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) && !readMethod.isAccessible()) {
                  //如果使用了JDK的安全机制,则需要权限验证  
                    if(System.getSecurityManager() != null) {
                        AccessController.doPrivileged(new PrivilegedAction<Object>() {
                            public Object run() {
                                readMethod.setAccessible(true);
                                return null;
                            }
                        });
                    } else {
                        readMethod.setAccessible(true);
                    }
                }

                final Object value = valueToApply;
                if(System.getSecurityManager() != null) {
                    try {
                     //将属性值设置到属性上去  
                        AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                            public Object run() throws Exception {
                                readMethod.invoke(BeanWrapperImpl.this.object, new Object[]{value});
                                return null;
                            }
                        }, this.acc);
                    } catch (PrivilegedActionException var17) {
                        throw var17.getException();
                    }
                } else {
                    readMethod.invoke(this.object, new Object[]{valueToApply});
                }
            } catch (TypeMismatchException var23) {
                throw var23;
            } catch (InvocationTargetException var24) {
                propertyChangeEvent = new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, propValue, pv.getValue());
                if(var24.getTargetException() instanceof ClassCastException) {
                    throw new TypeMismatchException(propertyChangeEvent, pd.getPropertyType(), var24.getTargetException());
                }

                throw new MethodInvocationException(propertyChangeEvent, var24.getTargetException());
            } catch (Exception var25) {
                propertyChangeEvent = new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, propValue, pv.getValue());
                throw new MethodInvocationException(propertyChangeEvent, var25);
            }
        }

    }

很复杂的一个解析方法:将属性的值注入到Bean实例对象中情况如下:

1. 对于集合类型的属性,将其属性值解析为目标类型的集合后直接赋值给属性

2. 对于非集合类型的属性,大量使用了JDK的反射和内省机制,通过属性的getter方法(reader method)获取指定属性注入以前的值,同时调用属性的setter方法(writer method)为属性设置注入后的值。


依赖注入总结:

(一)DefaultListableBeanFactory父类AbstractBeanFactory根据Bean的状态定义(单例、存在、原型)进行构造方法分发。分发到AbstractAutowireCapableBeanFactory类的createBean方法

(二)createBean方法负责Bean实例要求状态判断以及再度分发到doCreateBean实现创建实例(再次配置判断)。并在doCreateBean再度分发去createBeanInstance去Bean所包含的Java对象实例以及去populateBean 方法对Bean属性的依赖注入进行处理(以此为责任分发中心)。

(三)在createBeanInstance方法中真正地根据之前的配置判断设置选择真正合适的构造器(自动装配、无参构造器);

(四)在populateBean 方法中真正地将Bean属性设置到生成的实例对象上 ,但在过程中注入依赖属性的是在applyPropertyValues方法(完成属性转换),调用BeanDefinitionValueResolver类调用resolveValueIfNecessary方法对属性值的解析,属性的真正注入实现在BeanWrapperImpl类。


好了,Spring应用、原理以及粗读源码系列(一)--框架总述、以Bean为核心的机制(IoC容器初始化以及依赖注入)讲完了,这个系列以应用为基本点,结合源码讲解那堆应用的机制原理,我会加快脚步学习,分享经验给大家,希望大家喜欢。欢迎在下面指出错误,共同学习!!你的点赞是对我最好的支持!!

更多内容,可以访问JackFrost的博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容