|
|
|
@ -0,0 +1,184 @@
|
|
|
|
|
# <center>Spring启动主要流程</center>
|
|
|
|
|
|
|
|
|
|
Spring框架源码版本5.3.x
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
### 框架源码的前置知识
|
|
|
|
|
|
|
|
|
|
* 设计模式
|
|
|
|
|
* 数据结构与算法
|
|
|
|
|
* 反射
|
|
|
|
|
* 多线程
|
|
|
|
|
* JVM
|
|
|
|
|
|
|
|
|
|
通过xml文件配置bean进行调试。
|
|
|
|
|
|
|
|
|
|
```xml
|
|
|
|
|
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" abstract="xxx" autowire="byName" autowire-candidate="default" depends-on="environment" init-method="afterPropertiesSet">
|
|
|
|
|
<!-- 注入数据库连接池 -->
|
|
|
|
|
<property name="dataSource" ref="dataSource"/>
|
|
|
|
|
</bean>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```Java
|
|
|
|
|
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml")
|
|
|
|
|
XXX xxbean = context.getBean(XXX.class);
|
|
|
|
|
xxbean.method();
|
|
|
|
|
context.close();
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### SSM框架项目中spring处理bean的主要流程
|
|
|
|
|
|
|
|
|
|
* 加载bean定义文件,一般是xml文件或者注解
|
|
|
|
|
* 解析bean定义文件
|
|
|
|
|
* 封装BeanDefinition
|
|
|
|
|
* 处理PostProcessor
|
|
|
|
|
* 准备监听器
|
|
|
|
|
* 创建代理(JDK或者Cglib),使用反射实例化
|
|
|
|
|
* 属性填充和初始化
|
|
|
|
|
* 销毁
|
|
|
|
|
|
|
|
|
|
beanFactory容器使用map保存创建的bean,map的key和value内容
|
|
|
|
|
|序号| Key | Value |
|
|
|
|
|
|----| ---- | ---- |
|
|
|
|
|
|1| String | Object |
|
|
|
|
|
|2| Class | Object |
|
|
|
|
|
|3| String | ObjectFactory |
|
|
|
|
|
|4| String | BeanDefinition |
|
|
|
|
|
|4| String | lambda表达式 |
|
|
|
|
|
|
|
|
|
|
## Spring创建Bean过程中用到的主要接口和类
|
|
|
|
|
|
|
|
|
|
* BeanDefinitionReader
|
|
|
|
|
* BeanDefinition
|
|
|
|
|
* BeanFactory
|
|
|
|
|
* FactoryBean
|
|
|
|
|
* DefaultListableBeanFactory
|
|
|
|
|
* ClassPathXmlApplicationContext
|
|
|
|
|
* BeanPostProcessor
|
|
|
|
|
* BeanFactoryPostProcessor
|
|
|
|
|
* Aware
|
|
|
|
|
* BeanNameAware
|
|
|
|
|
* AbstractAutoProxyCreator
|
|
|
|
|
* ConfigurationClassPostProcessor
|
|
|
|
|
|
|
|
|
|
#### BeanDefinitionReader
|
|
|
|
|
|
|
|
|
|
  指定带有Resource或者字符串参数的加载方法的bean definition的简单接口。根据定义格式(xml、properties、yaml、注解),具体的reader可以添加额外的加载和注册方法。
|
|
|
|
|
|
|
|
|
|
#### BeanDefinition
|
|
|
|
|
|
|
|
|
|
  BeanDefinition描述带有属性值、构造器参数值、具体实现类的信息。
|
|
|
|
|
这是一个最小的接口,主要使BeanFactoryPostProcessor可以自省和修改属性值和其他的bean元数据。
|
|
|
|
|
|
|
|
|
|
#### BeanFactory
|
|
|
|
|
|
|
|
|
|
  访问Spring Bean容器的根接口。它是bean容器的基本客户端视图,进一步的接口如ListableBeanFactory和ConfigurableBeanFactory可用于指定的目的。
|
|
|
|
|
|
|
|
|
|
  这个接口被持有许多bean定义的对象实现,每一个对象都由字符串唯一确定。依据bean定义,factory将返回一个容器化对象的独立实例(原型设计模式),或者一个单例的共享对象(单例设计模式的一个更好的替代方案,该实例在factory内部是单例的)。那种类型的实例会被返回依赖于factory的配置,API是相同的。从Spring2.0开始,根据具体应用上下文,更多的范围可以被使用(比如web环境中的request和session)。
|
|
|
|
|
|
|
|
|
|
  这种方法的要点是BeanFactory是应用程序组件的中央注册表,并且集中了应用程序组件的配置(例如单个对象不再需要读取属性文件)。可以通过<Expert One-on-One J2EE Design and Development>的第4章和11章了解这种方式的优点。(到底是啥优点?)
|
|
|
|
|
|
|
|
|
|
  一般来讲,依靠DI(push配置)通过set或者构造方法配置应用对象是比使用任何形式,比如查找BeanFactory拉取配置要好的。Spring的依赖注入功能是使用BeanFactory接口和它的子接口实现的。
|
|
|
|
|
|
|
|
|
|
  通常一个BeanFactory将会加载保存在配置源(比如xml文档)中的bean定义,使用org.springframework.beans包配置bean。但是,实现可以简单地返回它根据需要直接在 Java 代码中创建的 Java 对象。bean定时可以被怎样储存是没有任何限制的,可以使用LDAP、RDBMS、XML、properties文件等。鼓励实现支持 bean 之间的引用(依赖注入)。
|
|
|
|
|
|
|
|
|
|
  与ListableBeanFactory中的方法相比,如果它是一个HierarchicalBeanFactory,这个接口的所有操作也会检查父工厂。如果一个bean没有在这个工厂实例中找到,会在直接父工厂中查找。这个工厂实例中的 bean 应该覆盖任何父工厂中的同名 bean。
|
|
|
|
|
|
|
|
|
|
  BeanFactory的实现类应该尽可能支持标准的bean生命周期接口。所有的初始化方法和顺序为
|
|
|
|
|
|
|
|
|
|
* BeanNameAware's {@code setBeanName}
|
|
|
|
|
* BeanClassLoaderAware's {@code setBeanClassLoader}
|
|
|
|
|
* BeanFactoryAware's {@code setBeanFactory}
|
|
|
|
|
* EnvironmentAware's {@code setEnvironment}
|
|
|
|
|
* EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
|
|
|
|
|
* ResourceLoaderAware's {@code setResourceLoader}
|
|
|
|
|
* ApplicationEventPublisherAware's {@code setApplicationEventPublisher} (only applicable when running in an application context)
|
|
|
|
|
* MessageSourceAware's {@code setMessageSource} (only applicable when running in an application context)
|
|
|
|
|
* ApplicationContextAware's {@code setApplicationContext} (only applicable when running in an application context)
|
|
|
|
|
* ServletContextAware's {@code setServletContext} (only applicable when running in an application context)
|
|
|
|
|
* {@code postProcessBeforeInitialization} methods of BeanPostProcessors (only applicable when running in a web application context)
|
|
|
|
|
* InitializingBean's {@code afterPropertiesSet}
|
|
|
|
|
* a custom {@code init-method} definition
|
|
|
|
|
* {@code postProcessAfterInitialization} methods of BeanPostProcessors
|
|
|
|
|
|
|
|
|
|
  bean工厂关闭的时候,会调用DestructionAwareBeanPostProcessors的postProcessBeforeDestruction()方法,DisposableBean的destroy()方法,自定义的destroy-method方法
|
|
|
|
|
|
|
|
|
|
#### FactoryBean
|
|
|
|
|
|
|
|
|
|
  由BeanFactory中使用的对象实现的接口,这些对象本身就是单个对象的工厂。 如果一个 bean 实现了这个接口,它就被用作一个对象的工厂来暴露,而不是直接作为一个将暴露自己的 bean 实例。
|
|
|
|
|
  实现此接口的 bean 不能用作普通 bean。 FactoryBean 以 bean 样式定义,但为 bean 引用暴露的对象 getObject() 始终是它创建的对象。
|
|
|
|
|
  FactoryBeans 可以支持单例和原型,并且可以根据需要懒惰地创建对象,也可以在启动时急切地创建对象。SmartFactoryBean接口允许公开更细粒度的行为元数据。
|
|
|
|
|
  此接口在框架本身中大量使用,例如 AOP org.springframework.aop.framework.ProxyFactoryBean 或 org.springframework.jndi.JndiObjectFactoryBean。 它也可以用于自定义组件;但是,这仅适用于基础设施代码。
|
|
|
|
|
  FactoryBean 是一个编程约定。实现不应该依赖于注解驱动的注入或其他反射设施。getObjectType() 和getObject() 调用可能在启动过程的早期到达,甚至在任何后处理器设置之前。 如果您需要访问其他 bean,请实现BeanFactoryAware并以编程方式获取它们。
|
|
|
|
|
  容器只负责管理 FactoryBean 实例的生命周期,而不负责管理 FactoryBean 创建的对象的生命周期。 因此,暴露的 bean 对象(例如 java.io.Closeable#close())上的 destroy 方法不会被自动调用。 相反,FactoryBean 应该实现 DisposableBean 并将任何此类关闭调用委托给底层对象。
|
|
|
|
|
  最后,FactoryBean 对象参与包含 BeanFactory 的 bean 创建同步。 除了在 FactoryBean 本身(或类似的)中进行惰性初始化之外,通常不需要内部同步。
|
|
|
|
|
|
|
|
|
|
#### DefaultListableBeanFactory
|
|
|
|
|
|
|
|
|
|
  Spring对ConfigurableListableBeanFactory和BeanDefinitionRegistry接口的默认实现,基于 bean 定义元数据的成熟的 bean 工厂,可通过后处理器进行扩展。
|
|
|
|
|
|
|
|
|
|
  典型用法是在访问bean前先注册所有 bean 定义(很可能是从一个bean定义文件中读取的)。在本地bean定义表中,在预先解析的bean定义元数据上操作,按照名称查找bean是一项廉价操作。
|
|
|
|
|
|
|
|
|
|
  特定bean定义格式的reader都是被分开实现的,而不是作为bean工厂的子类,可以参考XmlBeanDefinitionReader。
|
|
|
|
|
|
|
|
|
|
  对于ListableBeanFactory接口的替代实现,可以参考StaticListableBeanFactory,它管理已经存在的bean实例,而不是根据bean定义创建新的bean。
|
|
|
|
|
|
|
|
|
|
#### ClassPathXmlApplicationContext
|
|
|
|
|
|
|
|
|
|
  独立的 XML 应用程序上下文,从类路径中获取上下文定义文件,将普通路径解释为包含包路径的类路径资源名称(比如"mypackage/myresource.txt")。对于测试工具以及嵌入在 JAR 中的应用程序上下文很有用。
|
|
|
|
|
|
|
|
|
|
  配置位置默认值可以通过 {@link #getConfigLocations} 覆盖,配置位置可以表示为具体文件,比如"myfiles/context.xml",或者Ant风格类型,比如"myfiles/*-context.xml"(参考AntPathMatcher的java文档)。
|
|
|
|
|
|
|
|
|
|
  注意:在多个配置位置的情况下,后面的 bean 定义将覆盖前面加载文件中定义的那些。 这可以用来通过额外的 XML 文件故意覆盖某些 bean 定义。
|
|
|
|
|
|
|
|
|
|
  这是一个简单的、一站式便利的 ApplicationContext。考虑使用GenericApplicationContext类结合XmlBeanDefinitionReader进行更灵活的上下文设置。
|
|
|
|
|
|
|
|
|
|
#### BeanPostProcessor
|
|
|
|
|
|
|
|
|
|
  允许自定义修改新 bean 实例的工厂钩子——例如,检查标记接口或使用代理包装 bean。
|
|
|
|
|
|
|
|
|
|
  通常,后处理器通过标记接口填充bean或类似的将实现{@link #postProcessBeforeInitialization},而用代理包装 bean 的后处理器通常会实现{@link #postProcessAfterInitialization}。
|
|
|
|
|
|
|
|
|
|
  ApplicationContext可以在其 bean 定义中自动检测 BeanPostProcessor bean,并将这些后处理器应用于随后创建的任何 bean。普通的 BeanFactory 允许后处理器的编程注册,将它们应用于通过 bean 工厂创建的所有 bean。
|
|
|
|
|
|
|
|
|
|
  在 ApplicationContext 中自动检测到的 BeanPostProcessor bean 将根据 org.springframework.core.PriorityOrdered 和 org.springframework.core.Ordered 语义进行排序。相反,使用 BeanFactory 以编程方式注册的 BeanPostProcessor bean 将按注册顺序应用;对于以编程方式注册的后处理器,将忽略通过实现 PriorityOrdered 或 Ordered 接口表达的任何排序语义。此外, org.springframework.core.annotation.Order @Order 注解没有被考虑用于 BeanPostProcessor bean。
|
|
|
|
|
|
|
|
|
|
#### BeanFactoryPostProcessor
|
|
|
|
|
|
|
|
|
|
  允许自定义修改应用程序上下文的 bean 定义的工厂钩子,调整上下文底层 bean 工厂的 bean 属性值。
|
|
|
|
|
|
|
|
|
|
  对于针对系统管理员的自定义配置文件很有用,这些配置文件会覆盖在应用程序上下文中配置的 bean 属性。 请参阅 {@link PropertyResourceConfigurer} 及其具体实现,以了解满足此类配置需求的现成解决方案。
|
|
|
|
|
|
|
|
|
|
  BeanFactoryPostProcessor 可以与 bean 定义交互并修改 bean 定义,但绝不能与 bean 实例交互。 这样做可能会导致 bean 过早实例化,违反容器并导致意外的副作用。 如果需要 bean 实例交互,请考虑改为实施 BeanPostProcessor。
|
|
|
|
|
|
|
|
|
|
  ApplicationContext 自动检测其 bean 定义中的 BeanFactoryPostProcessor bean,并在创建任何其他 bean 之前应用它们。 BeanFactoryPostProcessor 也可以通过 ConfigurableApplicationContext} 以编程方式注册。
|
|
|
|
|
|
|
|
|
|
  在 ApplicationContext 中自动检测到的 BeanFactoryPostProcessor bean 将根据 org.springframework.core.PriorityOrdered 和 org.springframework.core.Ordered 语义进行排序。 相反,使用 ConfigurableApplicationContext 以编程方式注册的 BeanFactoryPostProcessor beans 将按注册顺序应用; 对于以编程方式注册的后处理器,将忽略通过实现 PriorityOrdered 或 Ordered 接口表达的任何排序语义。 此外, org.springframework.core.annotation.Order @Order 注释未被考虑用于 BeanFactoryPostProcessor beans。
|
|
|
|
|
|
|
|
|
|
#### Aware
|
|
|
|
|
|
|
|
|
|
  一个标记父接口,指示一个 bean 有资格通过回调样式的方法被特定框架对象的 Spring 容器通知。 实际的方法签名由各个子接口确定,但通常应该只包含一个接受单个参数的返回 void 的方法。
|
|
|
|
|
|
|
|
|
|
  请注意,仅实现 Aware 不提供默认功能。相反,处理必须显式完成,例如在 org.springframework.beans.factory.config.BeanPostProcessor 中。 有关处理特定 *Aware 接口回调的示例,请参阅 org.springframework.context.support.ApplicationContextAwareProcessor。
|
|
|
|
|
|
|
|
|
|
#### BeanNameAware
|
|
|
|
|
|
|
|
|
|
  由想要在 bean 工厂中了解其 bean 名称的 bean 实现的接口。 请注意,通常不建议对象依赖于其 bean 名称,因为这表示对外部配置的潜在脆弱依赖,以及对 Spring API 的可能不必要的依赖。
|
|
|
|
|
|
|
|
|
|
#### AbstractAutoProxyCreator
|
|
|
|
|
|
|
|
|
|
  org.springframework.beans.factory.config.BeanPostProcessor 的实现,用 AOP 代理包装每个符合条件的 bean,在调用 bean 本身之前委托给指定的拦截器。
|
|
|
|
|
|
|
|
|
|
  这个类区分“通用”拦截器:为它创建的所有代理共享,以及“特定”拦截器:每个 bean 实例唯一。不需要任何公共拦截器。如果有,则使用 interceptorNames 属性设置它们。 与 org.springframework.aop.framework.ProxyFactoryBean 一样,使用当前工厂中的拦截器名称而不是 bean 引用来允许正确处理原型顾问程序和拦截器:例如,支持有状态混合。#setInterceptorNames "interceptorNames" 条目支持任何建议类型。
|
|
|
|
|
|
|
|
|
|
  如果有大量的 beans 需要用类似的代理包装,即委托给相同的拦截器,那么这种自动代理特别有用。 您可以向 bean 工厂注册一个这样的后处理器,而不是为 x 个目标 bean 重复定义 x 个代理,以达到相同的效果。
|
|
|
|
|
|
|
|
|
|
  子类可以应用任何策略来决定是否要代理一个 bean,例如 按类型、按名称、按定义详细信息等。它们还可以返回应仅应用于特定 bean 实例的其他拦截器。 一个简单的具体实现是 {@link BeanNameAutoProxyCreator},通过给定名称识别要代理的 bean。
|
|
|
|
|
|
|
|
|
|
  可以使用任意数量的 TargetSourceCreator 实现来创建自定义目标源:例如,池化原型对象。 即使没有建议,自动代理也会发生,只要 TargetSourceCreator 指定自定义 org.springframework.aop.TargetSource。 如果没有设置 TargetSourceCreators,或者没有匹配项,默认情况下将使用 org.springframework.aop.target.SingletonTargetSource 来包装目标 bean 实例。
|
|
|
|
|
|
|
|
|
|
#### ConfigurationClassPostProcessor
|
|
|
|
|
|
|
|
|
|
  启动过程中处理@Configuration注解。通过\<context:annotation-config/>或者\<context:component-scan/>标签注册,也可以通过其他BeanFactoryPostProcessor手动注册。他实现了PriorityOrdered接口,@Configuration注解修饰的类中所有具有bean定义的方法在所有BeanFactoryPostProcessor执行之前注册。
|