Spring源码分析

Spring源码的核心就是工厂 也是我们常说的容器。

而ApplicationContext是高级工厂 类似于mybatis的sqlSession。

了解Spring的源码 需要首先弄清楚BeanFactory和FactoryBean有什么区别?

BeanFactory和FactoryBean

BeanFactory是个Factory,也就是Ico容器或者是对象工厂,而FactoryBean就是个Bean。 在Spring中,所有的bean都是由BeanFactory(IOC容器)来进行管理的。但是对于FactoryBean而言,这个bean不是个简单的bean,而是一个能生产或者修饰对象生成的工厂bean。

1.BeanFactory

BeanFactory定义了IOC容器的最基本形式, 并且提供了IOC容器应该遵守的最基本的接口,也就是Spring IOC所遵守的最底层和最基本的编程规范。在Spring源码中,BeanFacotry只是个接口,并不是IOC容器的具体实现,但是spring容器给除了很多种实现,例如:DefaultListbaBeanFactory,XmlBeanFactory,ApplicatonContext等,都是附加了某种功能的实现。

BeanFaoctry接口:

基本操作:

package org.springframework.beans.factory;  
import org.springframework.beans.BeansException;  
public interface BeanFactory {  
    String FACTORY_BEAN_PREFIX = "&";  
    Object getBean(String name) throws BeansException;  
     T getBean(String name, Class requiredType) throws BeansException;  
     T getBean(Class requiredType) throws BeansException;  
    Object getBean(String name, Object... args) throws BeansException;  
    boolean containsBean(String name);  
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;  
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;  
    boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException;  
    Class getType(String name) throws NoSuchBeanDefinitionException;  
    String[] getAliases(String name);  
}   

   BeanFacotry的结构:

BeanFactory: 共有四个实现(三个接口,一个实现)

        1.HierarchicalBeanFactory

        2.SimpleJndiBeanFactory(一般不用)

        3.AutowireCapableBeanFactory

        4.ListablBeanFactory

Spring源码分析_第1张图片

 对于BeanFacgtory在最终的实现类中, 大部分都是由DefaultListableBeanFactory,所以说这个DefaultListableBeanFacotry包含了大部分BeanFacotry的功能,是个大成者。Spring源码分析_第2张图片

 HierarchicalBeanFactory:有个两个实现接口:

        1.ConfigurableBeanFactory

                可配置工厂: 单实例、多实例的scope类型、 类型转换、后置处理bean等

        2.ApplicatonContext

AutowireCapabelBeanFactory: 具有InitialBean、 DisposeBean等作用

ListableBeanFactory: 获取bena的相关配置信息

而对于DefaultListablBeanFactory来说 符合上述大部分工厂的接口实现

XmlBeanFactory继承于DefaultListbaleBeanFacotry的一个实现,作用是读取xml的配置信息,完成对象的创建。核心是依靠于XMLBeanDefinitionReader这个类。

ApplicatonContext 是集工厂功能大成的类型编程,面向开发

Spring源码分析_第3张图片

 代码实现:


    @Test
    public void test1(){
        //过时写法
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
        User u = (User)beanFactory.getBean("u");
        System.out.println("u = " + u);

        //DefaultListablBeanFactory 是beanfactory的大成者 包含了大部分BeanFactory的功能
        DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(defaultListableBeanFactory);
        reader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml"));
        User user = defaultListableBeanFactory.getBean("u", User.class);
        System.out.println("user = " + user);

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        User appUser = (User)applicationContext.getBean("u");
        System.out.println("appUser = " + appUser);
    }

最终都会打印:

11:49:51.150 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 1 bean definitions from class path resource [applicationContext.xml]
11:49:51.157 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanFactory - Creating shared instance of singleton bean 'u'
u = User{id=10, name='zhangsan'}
11:49:51.361 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 1 bean definitions from class path resource [applicationContext.xml]
11:49:51.362 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'u'
user = User{id=10, name='zhangsan'}
11:49:51.387 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@177bea38
11:49:51.488 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 1 bean definitions from class path resource [applicationContext.xml]
11:49:51.558 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'u'
appUser = User{id=10, name='zhangsan'}

2.FactoryBean

Spring创建的对象有两种,一个是简单对象,另外一个是复杂对象(FactoryBean)

一般情况下,spring 通过反射机制利用bean的class属性指定实现类实例化Bean,在某些i情况下,实例化bena过程比较复杂,如果按照传统的方式, 则许哟啊在bean提供大量的配置信息。配置方式的灵活比较受限,spring提供了一个org.springframword.bean.factory.FactoryBean的工厂接口,用户可以通过实现这个接口定制实例化bean的逻辑。

FactoryBean接口对于spring框架来说占有比较重要地位。spring提供了70多种FactoryBean的实现,他们隐藏了一下复杂bean的细节,给上层带来了便利。从spring3.0来时,FactoryBean开始支持泛型,即接口声明改成了FactoryBean的形式。

package org.springframework.beans.factory;  
public interface FactoryBean {  
    T getObject() throws Exception;  
    Class getObjectType();  
    boolean isSingleton();  
}   

当调用一个类实现FactoryBean的时候,getBean(),spring通过反射机制发现了实现了FactoryBean的接口,这时spring容器就会调用接口方法的getObject方法。如果想要获取实现FactoryBean的类实现对象,则需要在使用getBean()方法的时候 在beanName上加&前缀。

分析:

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) ctx.getBean("u");

在读取配置文件的过程汇总,主要发生了什么?

以XmlBeanFactory为例:

1. 读取XML配置文件,XML配置文件 封装 Java对象 ---> 创建工厂生产的对象
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
2. 从工厂容器中获得对象
User user = (User) beanFactory.getBean("u");

过程读取:

        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));

首先

XmlBeanFactory 继承了DefaultListbaleBeanFactory接口, 在XmlBeanFactory实现类中,定义了一个XmlBeanDefinitionReader 对象,这个对象的作用就是为了读取xml配置文件,通过对象调用Resource顶级接口,在创建XmlBeanFacotry中,我们创建一个了ClassPathResource对象,传入了文件路径。

 对于Resource接口来说,不仅能都读取磁盘中的 .xml  .properties .txt等文件,还可以读取网络中的文件。实现Resource接口,有很多的实现类,例如:ClassPathResource. FileSystemResource, ByteArrayResource等

如图:

Spring源码分析_第4张图片

通过XmlBeanDefinitonReader来读取文件

 

InputSource是解析xml的一种方式

XML解析 
mybatis xml解析 xpath 
spring   xml解析 SAX 

Spring源码分析_第5张图片

 

 Spring源码分析_第6张图片

 通过前置获取的BeanDefinitonDocumentReader对象调用其接口提供的方法:

Spring源码分析_第7张图片

 DefaultBeanDefintionDocumentReader实现了BeanDefinitionDocumentReader接口,重写了其接口方法

Spring源码分析_第8张图片

 

 其中Element入参是前置传入document对象的属性 目的是通过元素 加载beandefintion的对象

Spring源码分析_第9张图片

 Spring源码分析_第10张图片

 Spring源码分析_第11张图片

 Spring源码分析_第12张图片

BeanDefintionHolder类:

Spring源码分析_第13张图片 

 

你可能感兴趣的:(spring,java,spring,boot)