Spring源码笔记

目录

  • IOC
    • 解析配置的方式
    • 核心接口与类
      • Bean
      • BeanDefinition
        • 常用属性
    • Spring 简单容器容器
      • BeanFactory接口
      • FactoryBean接口
      • ListableBeanFactory接口
      • HierarchicalBeanFactory接口
      • AutowireCapableBeanFactory接口
      • ConfigurableBeanFactory接口
      • DefaultListableBeanFactory接口
    • Spring高级容器(上下文)
      • ApplicationContext
      • ApplicationContext常用容器实现
        • 传统的基于XML配置的经典容器
        • 基于注解配置
      • ConfigurableApplicationContext
      • AbstractApplicationContext
    • Resource,ResourceLoader和容器之间的微妙关系
      • Resource接口
      • EncodedResource
      • AbstractResource
      • Ant-style正则表达式
      • ResourceLoader接口
        • DefaultResourceLoader
        • BeanDefinitionReader
        • BeanDefinitionDocumentReader
        • BeanDefinitionRegistry
    • 容器初始化主要脉络
      • xml配置的资源定位、加载、解析、注册
  • AOP
  • MVC

IOC

解析配置的方式

  1. 读取xml文件
  2. 注解配置类

核心接口与类

Bean

  1. Bean的本质就是java对象,只是这个对象的声明周期由周期来管理
  2. 不需要为了创建Bean而在原来的java类上添加任何额外的限制
  3. 对java对象的控制方式体现在配置上

BeanDefinition

BeanDefinition是bean在spring中的描述,有了BeanDefinition我们就可以创建Bean,BeanDefinition是Bean在spring中的定义形态

常用属性

  1. 作用范围scope(@Scope)
  2. 懒加载lazy-init(@Lazy):决定Bean实例是否延迟加载
  3. 首选primary(@Primary):设置为true 的bean会是优先的实现类
  4. factory-beanfactory-method(@Configuration@Bean)

Spring 简单容器容器

Spring源码笔记_第1张图片

BeanFactory接口

BeanFactory,以Factory结尾,表示它是一个工厂类(接口), 它负责生产和管理bean的一个工厂。

在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

所有ioc容器都需要实现该接口。

public interface BeanFactory {

	//对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,
	//如果需要得到工厂本身,需要转义
	String FACTORY_BEAN_PREFIX = "&";

	//根据bean的名字,获取在IOC容器中得到bean实例
	Object getBean(String name) throws BeansException;

	//根据bean的名字和Class类型来得到bean实例,增加了类型安全验证机制。
	<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;

	Object getBean(String name, Object... args) throws BeansException;

	<T> T getBean(Class<T> requiredType) throws BeansException;

	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

	//提供对bean的检索,看看是否在IOC容器有这个名字的bean
	boolean containsBean(String name);

	//根据bean名字得到bean实例,并同时判断这个bean是不是单例
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

	boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

	//得到bean实例的Class类型
	@Nullable
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;

	//得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
	String[] getAliases(String name);
}

FactoryBean接口

一个能生产或修饰对象生成的工厂Bean,类似于设计模式中的工厂模式和装饰器模式。它能在需要的时候生产一个对象,且不仅仅限于它自身,它能返回任何Bean的实例。

public interface FactoryBean<T> {

	//从工厂中获取bean
	@Nullable
	T getObject() throws Exception;

	//获取Bean工厂创建的对象的类型
	@Nullable
	Class<?> getObjectType();

	//Bean工厂创建的对象是否是单例模式
	default boolean isSingleton() {
		return true;
	}
}

从它定义的接口可以看出,FactoryBean表现的是一个工厂的职责。 即一个Bean A如果实现了FactoryBean接口,那么A就变成了一个工厂,根据A的名称获取到的实际上是工厂调用getObject()返回的对象,而不是A本身,如果要获取工厂A自身的实例,那么需要在名称前面加上&符号。

  1. getObject('name')返回工厂中的实例
  2. getObject('&name')返回工厂本身的实例

通常情况下,bean 无须自己实现工厂模式,Spring 容器担任了工厂的 角色;但少数情况下,容器中的 bean 本身就是工厂,作用是产生其他 bean 实例。由工厂 bean 产生的其他 bean 实例,不再由 Spring 容器产生,因此与普通 bean 的配置不同,不再需要提供 class 元素。

ListableBeanFactory接口

最大的特点就是可以列出工厂可以生产的所有实例及其属性。

HierarchicalBeanFactory接口

这个工厂接口非常简单,实现了Bean工厂的分层。这个工厂接口也是继承自BeanFacotory,也是一个二级接口,相对于父接口,它只扩展了一个重要的功能——工厂分层。

  1. 第一个方法返回本Bean工厂的父工厂。这个方法实现了工厂的分层。

  2. 第二个方法判断本地工厂是否包含这个Bean(忽略其他所有父工厂)。这也是分层思想的体现。

AutowireCapableBeanFactory接口

这个工厂接口继承自BeanFacotory,它扩展了自动装配的功能,根据类定义BeanDefinition装配Bean、执行前、后处理器等。

ConfigurableBeanFactory接口

继承自HierarchicalBeanFactorySingletonBeanRegistry 这两个接口
ConfigurableBeanFactory定义BeanFactory的配置.ConfigurableBeanFactory中定义了太多太多的api,比如类加载器,类型转化,属性编辑器,BeanPostProcessor,作用域,bean定义,处理bean依赖关系,合并其他ConfigurableBeanFactory,bean如何销毁.

DefaultListableBeanFactory接口

spring Ioc容器的实现,从根源上是beanfactory,但真正可以作为一个可以独立使用的ioc容器还是DefaultListableBeanFactory,因此可以这么说,DefaultListableBeanFactory 是整个spring ioc的始祖
默认实现了ListableBeanFactory和BeanDefinitionRegistry接口,基于bean definition对象,是一个成熟的bean factroy。

Spring高级容器(上下文)

ApplicationContext

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver{...}
  1. EnvironmentCapable获取环境
  2. ListableBeanFactory 以列表的方式管理Bean
  3. HierarchicalBeanFactory多层级的容器
  4. MessageSource解决message的能力,即支持国际化
  5. ApplicationEventPublisher让容器拥有发布应用上下文事件的功能,包括容器的启动事件、关闭事件等
  6. ResourcePatternResolver加载资源文件

ApplicationContext中没有set方法,只有get读取方法。

ApplicationContext常用容器实现

传统的基于XML配置的经典容器

  1. FileSystemXmlApplicationContext从文件系统下的一个或多个XML 配置文件加载上下文定义。
  2. ClassPathXMLApplicationContext从类路径下的一个或多个XML 配置文件加载上下文定义。
  3. XmlWebApplicationContext从Web 应用下的一个或多个XML 配置文件中加载上下文定义。

基于注解配置

  1. AnnotationConfigServletWebServerApplicationContext
  2. AnnotationConfigReactiveWebServerApplicationContext
  3. AnnotationConfigApplicationContext

ConfigurableApplicationContext

ConfigurableApplicationContext 直接继承了 ApplicationContext, Lifecycle, Closeable 接口

Lifecycle接口则是负责对 context 的生命周期进行管理,提供了 start()stop() 以及 isRunning() 方法。
Closeable 接口是JDK提供的接口,用于关闭组件,释放资源。
所以 ConfigurableApplicationContext 接口的作用就是设置上下文 ID,设置父应用上下文,添加监听器,刷新容器refresh(),关闭容器close(),判断是否活跃isActive()等方法。其实简单看一下 ApplicationContext接口就会发现里面之后get方法,没有set方法,所以子接口就提供了set方法。

AbstractApplicationContext

AbstractApplicationContext是Spring应用上下文中最重要的一个类,这个抽象类中提供了几乎ApplicationContext的所有操作。主要有容器工厂的处理,事件的发送广播,监听器添加,容器初始化操作refresh方法,然后就是bean的生成获取方法接口等。

Resource,ResourceLoader和容器之间的微妙关系

Resource接口

public interface Resource extends InputStreamSource {  
    boolean exists();  
    boolean isReadable();  
    boolean isOpen();  
    URL getURL() throws IOException;  
    URI getURI() throws IOException;  
    File getFile() throws IOException;  
    long contentLength() throws IOException;  
    long lastModified() throws IOException;  
    Resource createRelative(String relativePath) throws IOException;  
    String getFilename();  
    String getDescription();  
}  

它是spring访问资源最基本的接口。实际访问的时候直接用Resource接口就可以,不必使用其子类。其实经常用到的(resource的真正目的)方法是public InputStream getInputStream()。

EncodedResource

主要实现了对资源文件的编码处理。

AbstractResource

  1. ClassPathResource:通过 ClassPathResource 以类路径的方式进行访问;
  2. FileSystemResource:通过 FileSystemResource 以文件系统绝对路径的方式进行访问;
  3. ServletContextResource:通过 ServletContextResource 以相对于Web应用根目录的方式进行访问;

Ant-style正则表达式

? 匹配任何单字符
* 匹配0或者任意数量的字符
** 匹配0或者更多的目录

例如:
/app/*.x 匹配(Matches)所有在app路径下的.x文件
/app/p?ttern 匹配(Matches) /app/pattern 和 /app/pXttern,但是不包括/app/pttern
/**/example 匹配(Matches) /app/example, /app/foo/example,/example
/app/**/dir/file. 匹配(Matches) /app/dir/file.jsp, > /app/foo/dir/file.html,/app/foo/bar/dir/file.pdf,/app/dir/file.java
/**/*.jsp 匹配(Matches)任何的.jsp 文件

ResourceLoader接口

该接口中只定义了一个用于获取Resource的getResource(String location)方法。

DefaultResourceLoader

DefaultResourceLoader在获取Resource时采用的是这样的策略:首先判断指定的location是否含有“classpath:”前缀,如果有则把location去掉“classpath:”前缀返回对应的ClassPathResource;否则就把它当做一个URL来处理,封装成一个UrlResource进行返回;如果当成URL处理也失败的话就把location对应的资源当成是一个ClassPathResource进行返回。

BeanDefinitionReader

BeanDefinitionReader ,该接口的作用就是加载 Bean。

在 Spring 中,Bean 一般来说都在配置文件中定义。而在配置的路径由在 web.xml 中定义。所以加载 Bean 的步骤大致就是:

  1. 加载资源,通过配置文件的路径(Location)加载配置文件(Resource)
  2. 解析资源,通过解析配置文件的内容得到 Bean。

Spring配置文件的解析是通过BeanDefinitionReader来实现的,其实了解BeanDefinitionReader实现的机制就会发现,其只是将ApplicationContext的.xml配置文件解析成Document对象,真正对xml中元素解析的类是在BeanDefinitionDocumentReader的实现类中来完成的

BeanDefinitionDocumentReader

BeanDefinitionDocumentReader提供的方法:

public interface BeanDefinitionDocumentReader {
 
	void registerBeanDefinitions(Document doc, XmlReaderContext readerContext)
			throws BeanDefinitionStoreException;
 
}

DefaultBeanDefinitionDocumentReaderregisterBeanDefinitions方法中开始对Document进行解析。

	@Override
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		logger.debug("Loading bean definitions");
		Element root = doc.getDocumentElement();
		doRegisterBeanDefinitions(root);
	}

BeanDefinitionDocumentReader中也没有对xml中的bean元素进行处理操作,其真正的处理操作是在BeanDefinitionParserDelegate中进行处理的

BeanDefinitionRegistry

用于BeanDefinition的注册

容器初始化主要脉络

Spring源码笔记_第2张图片

xml配置的资源定位、加载、解析、注册

  1. FileSystemXmlApplicationContext读取xml配置文件路径
  2. 进入refresh()方法初始化容器
    1. refresh()中的obtainFreshBeanFactory()解析配置

AOP

MVC

你可能感兴趣的:(学习笔记)