Contents
  1. 1. 参考示例源代码:
  2. 2. 基本原理:
  3. 3. Spring 中核心类和接口
    1. 3.1. BeanFactory interface
    2. 3.2. BeanDefinition
    3. 3.3. XmlBeanFactory
    4. 3.4. DefaultSingletonBeanRegistry
    5. 3.5. HierarchicalBeanFactory
    6. 3.6. ApplicationContext
    7. 3.7. WebApplicationContext
  4. 4. web容器启动原理:
    1. 4.1. 具体过程
  5. 5. 通过BeanFactory生产类的流程
  6. 6. Tomcat中Spring的bean的创建过程
  7. 7. Spring的Bean生命周期
    1. 7.1. Bean 本身的方法
    2. 7.2. Bean级生命周期接口方法
    3. 7.3. 容器级生命周期接口方法
      1. 7.3.1. BeanPostProcessor,在每一个bean调用init方法执行前和执行后执行
      2. 7.3.2. 超级InstantiationAwareBeanPostProcessor接口,分别在实例化、设置属性值、初始化3个过程当中都干预bean的生命周期,甚至可以阻住bean的属性值设置是否执行

参考示例源代码:

https://github.com/huangzhenshi/SpringFreamworkDemo/tree/master

https://zhuanlan.zhihu.com/p/29344811

基本原理:

基本原理其实就是通过反射解析类及其类的各种信息,包括构造器、方法及其参数,属性。

然后将其封装成bean定义信息类、constructor信息类、method信息类、property信息类,最终放在一个map里,也就是所谓的container,池等等,其实就是个map

当你写好配置文件,启动项目后,框架会先按照你的配置文件找到那个要scan的包,然后解析包里面的所有类,找到所有含有@bean,@service等注解的类,利用反射解析它们,包括解析构造器,方法,属性等等,然后封装成各种信息类放到一个map里。每当你需要一个bean的时候,框架就会从container找是不是有这个类的定义啊?如果找到则通过构造器new出来(这就是控制反转,不用你new,框架帮你new),再在这个类找是不是有要注入的属性或者方法,比如标有@autowired的属性,如果有则还是到container找对应的解析类,new出对象,并通过之前解析出来的信息类找到setter方法,然后用该方法注入对象(这就是依赖注入)。如果其中有一个类container里没找到,则抛出异常,比如常见的spring无法找到该类定义,无法wire的异常。还有就是嵌套bean则用了一下递归,container会放到servletcontext里面,每次reQuest从servletcontext找这个container即可,不用多次解析类定义。如果bean的scope是singleton,则会重用这个bean不再重新创建,将这个bean放到一个map里,每次用都先从这个map里面找。如果scope是session,则该bean会放到session里面。

Spring 中核心类和接口

BeanFactory interface

顶层接口,也是实现工厂方式的抽象工厂,默认懒加载

  • getBean()
  • containsBean()
  • isSingleton\isPrototype()
    Car car = (Car) bf.getBean("car");
    Car car2 = bf.getBean("car",Car.class);

BeanDefinition

web容器会把所有的bean都注册到BeanDefinitionRegistry当中

  • bean本身的相关信息 getBeanClassName() isLazyInit() getPropertyValues() isSingleton()
  • 父类相关信息 getParentName()
  • 依赖类信息 getDependsOn()
  • 加载器相关信息 getFactoryBeanName()

XmlBeanFactory

常用的一个工厂实现类,读取spring.xml里面配置的bean

DefaultSingletonBeanRegistry

ConcurrentHashMap 存储各种注册的类的缓存池 类名/类基本信息Object K/V

<bean id="car" class="com.test.entity.Car">
<property name="brand" value="奥迪"></property>
<property name="color" value="黑色"></property>
<property name="maxSpeed" value="200"></property>
</bean>
this.singotonObjects--> car=com.test.entity.Car@5b02985

HierarchicalBeanFactory

建立父子级别容器的扩展类,MVC就是依赖这个工厂实现的

ApplicationContext

继承自 HierarchicalBeanFactory,除了继承了 父子容器 和创建bean还扩展了很多功能

  • ApplicationEventPublisher:让容器拥有发布应用上下文事件的功能,包括容器启动事件、关闭事件等。实现了 ApplicationListener 事件监听接口的 Bean 可以接收到容器事件 , 并对事件进行响应处理
  • LifeCycle:该接口实现生命周期管理
  • ResourcePatternResolver: 正则表达式 读取配置文件信息 application*.xml
    ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:application-datasource.xml");
    int count=ctx.getBeanDefinitionCount();//这里获取的是注册表中的数量不是实例化类的数量
    ctx.getBean("car");
    ctx.getBean("dataSource");
    public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
    MessageSource, ApplicationEventPublisher, ResourcePatternResolver {

WebApplicationContext

实现web容器和spring的整合,web启动时ServletContext有两种方式获取到WebApplicationContext

org.springframework.web.context.ContextLoaderServlet;
org.springframework.web.context.ContextLoaderListener
ServletContext getServletContext();

web容器启动原理:

  • tomcat启动触发web.xml,web容器提供SevletContext
  • 会根据ContextLoaderListener监听,或者ContextLoaderSevlet初始化WebApplicationContext
  • 读取指定路径下的bean配置文件,加载初始化所有的配置的或者注解的Bean存储到DefaultSingletonBeanRegistry缓存起来。
  • 再扫描web.xml的serlvet元素,比如MVC的DispatcherServlet,也会重复类似的过程,但是是在Spring的子容器IOC容器当中,父容器配置的元素对子容器可见。

具体过程

  • web.xml 的ContextLoaderListener最先执行,监听tomcat的容器启动,启动之后调用初始化方法,初始化一个 WebApplicationContext

    public void contextInitialized(ServletContextEvent event) {
    this.contextLoader = createContextLoader();
    if (this.contextLoader == null) {
    this.contextLoader = this;
    }
    this.contextLoader.initWebApplicationContext(event.getServletContext());
    }
  • 再通过配置的参数取读取配置文件

    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
    classpath*:application-datasource.xml
    </param-value>
    </context-param>
  • 再读取web.xml里面的servelt元素,初始化类似MVC的子容器,子容器初始化的过程是先拷贝一份父容器,也就是spring容器当中的类的信息,再读取MVC的配置文件,读取只属于MVC的子类,所以MVC里面的类对Spring容器不可见

    <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:application-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>*.do</url-pattern>
    </servlet-mapping>

通过BeanFactory生产类的流程

通过Resource指定配置文件的位置,并且启动IOC容器,但是不会实例化配置或者扫描的bean,只有在第一次调用getBean的时候,会初始化这个单例的对象并且存储在DefaultSingletonBeanRegistry的singletonObjects = new ConcurrentHashMap(64)中

ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource res = resolver.getResource("classpath:beans.xml");
BeanFactory bf = new XmlBeanFactory(res);
System.out.println("init BeanFactory.");
Car car = bf.getBean("car",Car.class);
this.registeredSingletons.add(beanName);

Tomcat中Spring的bean的创建过程

web容器的操作:

  • web容器启动的时候会读取到配置文件的地址context-param
  • ResourceLoader读取配置文件–>生成Resource对象
  • BeanDefinitionReader读取Resource,生成各种BeanDefinition,并存储在BeanDefinitionRegistry中

Spring执行操作:

  • Spring读取BeanDefinitionRegistry中的BeanDefinition,先对bean进行加工处理,最后如果是单例的话,存在DeaSinBeanRegi里面的hashmap中

Spring的Bean生命周期

生命周期概论:

  1. 简单的bean的生命周期就是 调用构造函数创建实例 – >设置属性(如果在xml里面有设置的话) –> 执行init方法(如果有配置) –> destroy(如果容器关闭时)
  2. 再此基础之上,可以让bean实现一些接口,来干预bean的实例化,比如设置beanName,BeanFactory,afterPropertiesSet、destroy等方法
  3. 最后还可以在容器级别上实现 构造函数、设置属性值、初始化 这3个过程当中的全局性所有bean的干预方法

Bean 本身的方法

public class SimpleBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("设置属性"+name);
this.name = name;
}
SimpleBean(){
System.out.println("执行构造函数");
}
public void init(){
System.out.println("init");
}
public void destroyBean(){
System.out.println("destorying");
}
}

结果

执行构造函数
设置属性Simple
init
destorying

配置和启动

<bean id="simple" class="com.test.domain.SimpleBean" init-method="init" destroy-method="destroyBean">
<property name="name" value="Simple"></property>
</bean>
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:beans.xml");
SimpleBean test=ctx.getBean("simple",SimpleBean.class);
((ClassPathXmlApplicationContext)ctx).close();

Bean级生命周期接口方法

  • BeanNameAware,bean设置完属性值后执行

    @Override
    public void setBeanName(String name) {
    System.out.println("setBeanName");
    }
  • BeanFactoryAware,setBeanName执行完后执行

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    System.out.println("setBeanFactory");
    }
  • InitializingBean,初始化方法调用之前执行

    @Override
    public void afterPropertiesSet() throws Exception {
    System.out.println("afterPropertiesSet");
    }
  • DisposableBean,容器要销毁之前执行,但是优先于 bean的destroy-method之前执行

    @Override
    public void destroy() throws Exception {
    System.out.println("destory");
    }

普通bean的执行顺序结果

执行构造函数
设置属性Spring
setBeanName
setBeanFactory
afterPropertiesSet
destory
destorying

容器级生命周期接口方法

容器级别的处理器,在创建所有的bean的时候都会调用

BeanPostProcessor,在每一个bean调用init方法执行前和执行后执行

  • 执行结果顺序

    执行构造函数
    设置属性Spring
    setBeanName
    setBeanFactory
    postProcessBeforeInitialization
    afterPropertiesSet
    init
    postProcessAfterInitialization
    destory
    destorying
  • 接口代码

    public class Processor implements BeanPostProcessor{
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
    throws BeansException {
    System.out.println("postProcessBeforeInitialization");
    return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
    throws BeansException {
    System.out.println("postProcessAfterInitialization");
    return bean;
    }
    }

超级InstantiationAwareBeanPostProcessor接口,分别在实例化、设置属性值、初始化3个过程当中都干预bean的生命周期,甚至可以阻住bean的属性值设置是否执行

  • 执行结果

    # 实例化干预
    实例化bean之前调用,即调用bean类构造函数之前调用 com.test.domain.SpringTest
    执行构造函数
    postProcessAfterInstantiation 返回boolean,bean实例化后调用,并且返回false则不会注入属性
    # 属性值设置干预
    postProcessPropertyValues,在属性注入之前调用...... beanName = test 属性名集合 : [bean property 'name']
    设置属性Spring
    setBeanName
    setBeanFactory
    # 初始化设置干预
    postProcessBeforeInitialization
    afterPropertiesSet
    init
    postProcessAfterInitialization
    destory
    destorying
  • 接口代码

    public class InstanceBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
    throws BeansException {
    System.out.println("postProcessBeforeInitialization");
    return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
    throws BeansException {
    System.out.println("postProcessAfterInitialization");
    return bean;
    }
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass,
    String beanName) throws BeansException {
    System.out.println("实例化bean之前调用,即调用bean类构造函数之前调用 " + beanClass.getName());
    return null;
    }
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName)
    throws BeansException {
    System.out.println("返回boolean,bean实例化后调用,并且返回false则不会注入属性");
    return true;
    }
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs,
    PropertyDescriptor[] pds, Object bean, String beanName)
    throws BeansException {
    System.out.println("postProcessPropertyValues,在属性注入之前调用...... beanName = " + beanName + " 属性名集合 : "
    + Arrays.toString(pvs.getPropertyValues()));
    return pvs;
    }
    }
Contents
  1. 1. 参考示例源代码:
  2. 2. 基本原理:
  3. 3. Spring 中核心类和接口
    1. 3.1. BeanFactory interface
    2. 3.2. BeanDefinition
    3. 3.3. XmlBeanFactory
    4. 3.4. DefaultSingletonBeanRegistry
    5. 3.5. HierarchicalBeanFactory
    6. 3.6. ApplicationContext
    7. 3.7. WebApplicationContext
  4. 4. web容器启动原理:
    1. 4.1. 具体过程
  5. 5. 通过BeanFactory生产类的流程
  6. 6. Tomcat中Spring的bean的创建过程
  7. 7. Spring的Bean生命周期
    1. 7.1. Bean 本身的方法
    2. 7.2. Bean级生命周期接口方法
    3. 7.3. 容器级生命周期接口方法
      1. 7.3.1. BeanPostProcessor,在每一个bean调用init方法执行前和执行后执行
      2. 7.3.2. 超级InstantiationAwareBeanPostProcessor接口,分别在实例化、设置属性值、初始化3个过程当中都干预bean的生命周期,甚至可以阻住bean的属性值设置是否执行