Spring 源码(一)Spring 容器的入口及简单介绍

说明:
1.本篇不讲述具体的Spring相关功能源码分析,仅对源码导读的一些前提做一些准备和记录

Spring 容器的初始化

 
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);

当我们完成一个ApplicationContext的实例化时就完成了Spring容器的初始化,而AnnotationConfigApplicationContext的构造方法也就是Spring容器的入口。

(IDEA当中可通过crtl+鼠标左键进入源码查看 ,此处我已简单的方式进行)

// 初始化容器
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    // 注册 Spring 内置后置处理器的 BeanDefinition 到容器
    this();
    // 注册配置类 BeanDefinition 到容器
    register(annotatedClasses);
    // 加载或者刷新容器中的Bean
    refresh();
}

这个构造方法只有三行:

  1. 注册内置的BeanPostProcessor的BeanDefinition到容器
  2. 注册配置类 BeanDefinition 到容器
  3. 加载或者刷新容器中的Bean

容器的初始化过程我认为大致分为:

  1. 注册内置的BeanPostProcessor的BeanDefinition到容器
  2. 注册配置类 BeanDefinition 到容器
  3. 解析配置类
  4. 初始化所有单例Bean,并注册到容器

AnnotationConfigApplicationContext 总揽

我们来看下AnnotationConfigApplicationContext的类图:

(进入AnnotationConfigApplicationContext-> 在Idea类中右键 ->查看类图)

 

 接下来我们来看具体Spring的相关结构

 

 (类图使用技巧:右键某个接口或者类可对整个类图的相关类属性进行查看,很多时候源码没法看细节性的东西,粗略的看下类结构及方法即可)

AnnotationConfigApplicationContext说明
  • BeanFactory:它定义了Spring IOC容器最基本的功能规范,主要用来实例化、配置和管理Bean,它是IOC容器容器的心胀。主要包括bean获取,单例多例判断,Bean类型及别名获取

  • HierarchicalBeanFactory:继承BeanFactory接口,新增了getParentBeanFactory()方法,使BeanFactory具备了双亲IOC容器的管理功能。

  • ListableBeanFactory:细化了许多BeanFactory接口的功能,比如getBeanDefinitionNames()方法(获取容器中所有Bean定义的名称)。

  • ResourceLoader:资源加载器。

  • MessageSource:支持不同的信息源,从而实现国际化。

  • ApplicationEventPublisher:支持应用事件,提供事件机制的定义。

  • EnvironmentCapable:提供了对环境变量的支持。

  • ApplicationContext:它继承了上述所有接口,是IOC容器的高级形态,它定了一个完成容器的雏形。(重点的类需要稍微记一下 方便后续进行回顾学习)

  • AbstractApplicationContext:一个容器的抽象实现

用户使用容器时,可以使用转义符"&"来得到FactoryBean本身,如果不加则是获取FactoryBean产生的对象。

BeanFactory和FactoryBean的区别

  • BeanFactory:它是对IOC容器所有Bean进行管理,如实例化,配置和获取容器中的Bean。
  • FactoryBean:它是一个能够生产或者修饰对象生成的工厂Bean。

BeanFactory :(通用bean处理)

  BeanFactory 是基础类型的 IoC 容器,它由 org.springframework.beans.facytory.BeanFactory 接口定义,并提供了完整的 IoC 服务支持。简单来说,BeanFactory 就是一个管理 Bean 的工厂,它主要负责初始化各种 Bean,并调用它们的生命周期方法。
BeanFactory 接口有多个实现类,最常见的是 org.springframework.beans.factory.xml.XmlBeanFactory,它是根据 XML 配置文件中的定义装配 Bean 的。
创建 BeanFactory 实例时,需要提供 Spring 所管理容器的详细配置信息,这些信息通常采用 XML 文件形式管理。其加载配置信息的代码具体如下所示:

BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("D://applicationContext.xml"));

FactoryBean:(复杂自定义bean处理)

  一般情况下,Spring通过反射机制利用<bean>的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在<bean>中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。从Spring3.0开始,FactoryBean开始支持泛型,即接口声明改为FactoryBean<T>的形式
 
下面简单给一个FactoryBean的例子
1.Bean的Resourse配置
<beans xmlns="http://www.springframework.org/schema/beans"  
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
             xmlns:context="http://www.springframework.org/schema/context"  
             xmlns:aop="http://www.springframework.org/schema/aop"  
             xmlns:tx="http://www.springframework.org/schema/tx"  
             xsi:schemaLocation="http://www.springframework.org/schema/beans  
                     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
                     http://www.springframework.org/schema/context  
                     http://www.springframework.org/schema/context/spring-context-3.0.xsd  
                     http://www.springframework.org/schema/aop  
                     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
                     http://www.springframework.org/schema/tx  
                     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">  
      
 <bean id="student" class="com.spring.bean.Student">    
  <property name="name" value="zhangsan" />    
 </bean>    
   
 <bean id="school" class="com.spring.bean.School">    
 </bean>   
   
 <bean id="factoryBeanPojo" class="com.spring.bean.FactoryBeanPojo">    
    <property name="type" value="student" />  
 </bean>   
</beans>

2. FactoryBean的实现类  实现FactoryBean  实现其接口方法  重写getObject等其他bean方法

import org.springframework.beans.factory.FactoryBean;  
  
public class FactoryBeanPojo implements FactoryBean{  
    private String type;  
  
    @Override  
    public Object getObject() throws Exception {  
        if("student".equals(type)){  
            return new Student();             
        }else{  
            return new School();  
        }  
          
    }  
  
    @Override  
    public Class getObjectType() {  
        return School.class;  
    }  
  
    @Override  
    public boolean isSingleton() {  
        return true;  
    }  
  
    public String getType() {  
        return type;  
    }  
  
    public void setType(String type) {  
        this.type = type;  
    }  
      
}

3.普通bean注册

public class School {  
    private String schoolName;  
    private String address;  
    private int studentNumber;  
    public String getSchoolName() {  
        return schoolName;  
    }  
    public void setSchoolName(String schoolName) {  
        this.schoolName = schoolName;  
    }  
    public String getAddress() {  
        return address;  
    }  
    public void setAddress(String address) {  
        this.address = address;  
    }  
    public int getStudentNumber() {  
        return studentNumber;  
    }  
    public void setStudentNumber(int studentNumber) {  
        this.studentNumber = studentNumber;  
    }  
    @Override  
    public String toString() {  
        return "School [schoolName=" + schoolName + ", address=" + address  
                + ", studentNumber=" + studentNumber + "]";  
    }  
}

public class Student {  
    private String name;    
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
}

 4.测试

import org.springframework.context.support.ClassPathXmlApplicationContext;  
  
import com.spring.bean.FactoryBeanPojo;  

public class FactoryBeanTest {  
    public static void main(String[] args){  
        String url = "com/spring/config/BeanConfig.xml";  
        ClassPathXmlApplicationContext cpxa = new ClassPathXmlApplicationContext(url);  
     //Bean工厂获取FactoryBean来获取bean
        Object school=  cpxa.getBean("factoryBeanPojo");  
     //获取自定义BeanFactory工厂   需要加&符号来标识
        FactoryBeanPojo factoryBeanPojo= (FactoryBeanPojo) cpxa.getBean("&factoryBeanPojo");  

        System.out.println(school.getClass().getName());  
        System.out.println(factoryBeanPojo.getClass().getName());  
    }  
}

  结果:

com.spring.bean.Student 
com.spring.bean.FactoryBeanPojo

  总结:BeanFacoty是SpringIOC容器的默认Bean管理,通过Factotybean可以自定义一些复杂的Bean

BeanFactory和ApplicationContext的区别

通过继承图我们可以发现

  • BeanFactory是容器的基本定义。
  • ApplicationContext继承自BeanFactory,是容器的高级形态,在BeanFactory的基础上添加了许多对高级容器特性的支持。

 其次:

BeanFactory:

BeanFactory在启动的时候不会去实例化Bean,有从容器中拿Bean的时候才会去实例化;

ApplicationContext:

ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化

posted @ 2020-08-19 14:24  胡小华  阅读(2085)  评论(0编辑  收藏  举报