Spring Framework 总结和面试题

核心特性(Core)

IoC容器(IoC Container)

Spring事件(Events)

资源管理(Resources)

国际化(i18n)

校验(Validation)

数据绑定(Data Binding)

类型转换(Type Conversion)

Spring表达式(Spring Express Language)

面向切面编程(AOP)

数据存储(Data Access)

  • JDBC
  • 事务抽象(Transactions)
  • DAO支持(DAO Support)
  • O/R映射(O/R Mapping)
  • XML编程(XML Marshalling)

Web技术

  • Web Servlet 技术栈

Spring MVC

WebSocket

SockJS

  • Web Reactive技术栈

Spring WebFlux

WebClient

WebSocket

技术整合(Integration)

远程调用(Remoting)

Java消息服务(JMS)

Java连接架构(JCA)

Java管理扩展(JMX)

Java邮件客户端(Email)

本地任务(Tasks)

本地调度(Scheduling)

缓存抽象(Caching)

Spring测试(Testing)

测试(Testing)

模拟对象(Mock Objects)

TestContext框架(TestContext Framework)

Spring MVC测试(Spring MVC Test)

Web测试客户端(WebTestClient)

Java 版本依赖与支持

Spring Framework 版本Java 标准版Java 企业版
1.x1.3+J2EE 1.3+
2.x1.4.2+J2EE 1.3+
3.x5+J2EE 1.4 和 Java EE 5
4.x6+Java EE 6 和 7
5.x8+Java EE 7

Spring 模块化设计(Modular)

spring-aop

spring-aspects

spring-context-indexer

spring-context-support

spring-context

spring-core

spring-expression

spring-instrument

spring-jcl

spring-jdbc

spring-jms

spring-messaging

spring-orm

spring-oxm

spring-test

spring-tx

spring-web

spring-webflux

spring-webmvc

spring-websocket

Java 语法变化

Spring 对 Java 语言特性运用

  • Java 5 语法特性
语法特性Spring 支持版本

代表实现

注解(Annotation)1.2+@Transactional
枚举(Enumeration)1.2+Propagation
for-each 语法3.0+AbstractApplicationContext
自动装箱(AutoBoxing)3.0+ 
泛型(Generic)3.0+ApplicationListener
  • Java 6 语法特性
语法特性Spring支持版本代表实现
接口@Override4.0+ 
  • Java 7 语法特性
语法特性Spring 支持版本代表实现
Diamond 语法5.0+DefaultListableBeanFactory
try-with-resources 语法5.0+ResourceBundleMessageSource
  • Java 8 语法特性
语法特性Spring 支持版本代表实现
Lambda 语法5.0+PropertyEditorRegistrySupport

Spring 对 JDK API 实践

  • < Java 5 API
API 类型Spring 支持版本代表实现
反射(Reflection)1.0+MethodMatcher
Java Beans1.0+CachedIntrospectionResults
动态代理(Dynamic Proxy)1.0+JdkDynamicAopProxy
  • Java 5 API
API类型Spring支持版本代表实现
XML处理(DOM,SAX....)1.0+XmlBeanDefinitionReader
Java 管理扩展(JMX)1.2+@ManagedResource
Instrumentation2.0+InstrumentationSavingAgent
并发框架(J.U.C)3.0+ThreadPoolTaskScheduler
格式化(Formatter)3.0+DateFormatter
  • Java 6 API
API类型Spring 支持版本代表实现
JDBC4.0(JSR 221)1.0+JdbcTemplate
Common Annotations(JSR 250)2.5+CommonAnnotationBeanPostProcessor
JAXB 2.0(JSR 222)3.0+jaxb2Marshaller
Scripting in JVM (JSR 223)4.2+StandardScriptFactory
可插拔注解处理 API (JSR 269)5.0+@Indexed
Java Compiler API (JSR 199)

5.0+

TestCompiler(单元测试)
  • Java 7 API
API 类型Spring 支持版本代表实现
Fork/Join框架(JSR 166)3.1+ForkJoinPoolFactoryBean
NIO 2 (JSR 203)4.0+PathResource
  • Java 8 API
API 类型Spring 支持版本代表实现
Date and Time API(JSR 310)4.0+DateTimeContext
可重复Annotations (JSR 337)4.0+@PropertySources
Stream API (JSR 335)4.2+StreamConverter
CompletableFuture(J.U.C)4.2+CompletableToListenableFutureAdapter

Spring 对 Java EE API 整合

  • Java EE Web 技术相关
JSR 规范Spring 支持版本代表实现
Servlet + JSP(JSR 035)1.0+DispatcherServlet
JSTL(JSR 052)1.0+JstlView
JavaServer Faces(JSR 127)1.1+FacesContextUtils
Portlet(JSR 168)2.0 - 4.2DispatcherProtlet
SOAP(JSR 067)2.5+SoapFaultException
WebServices(JSR 109)2.5+CommonAnnotationBeanPostProcessor
WebSocket(JSR 356)4.0+WebSocketHandler
  • Java EE 数据存储相关
JSR规范Spring 支持版本代表实现
JDO(JSR 12)1.0 - 4.2JdoTemplate
JTA(JSR 907)1.0+JtaTransactionManager
JPA(EJB 3.0  JSR 220)2.0+JpaTransactionManager
Java Caching API(JSR 107)3.2+JCacheCache
  • Java EE Bean 技术相关
JSR 规范Spring 支持技术代表实现
JMS(JSR 914)1.1+JmsTemplate
EJB 2.0(JSR 19)1.0+AbstractStatefulSessionBean
Dependency Injection for Java(JSR 330)2.5+AutowiredAnnotationBeanPostProcessor
Bean Validation(JSR 303)3.0+LocalValidatorFactoryBean

Spring 编程模型

 

什么是Spring Framework?

Spring makes it easy to create Java enterprise applications. It provides everything you need to embrace the Java language in an enterprise environment, with support for Groovy and Kotlin as alternative languages on the JVM, and with the flexibility to create many kinds of architectures depending on an application’s needs.

(Spring使创建Java企业应用程序变得很容易。它提供了在企业环境中使用Java语言所需的一切,支持Groovy和Kotlin作为JVM上的替代语言,并具有根据应用程序的需要创建多种体系结构的灵活性)

 

Spring Framework 有哪些核心模块?

  • spring-core:Spring 基础API模块,如资源管理,泛型处理
  • spring-beans:Spring Bean 相关,如依赖查找,依赖注入
  • spring-aop:Spring AOP处理,如动态代理,AOP字节码提升
  • spring-context:事件驱动,注解驱动,模块驱动等
  • spring-expression:Spring 表达式语言模块

 

IoC的定义

In software engineering, inversion of control (IoC) is a programming principle. IoC inverts the flow of control as compared to traditional control flow. In IoC, custom-written portions of a computer program receive the flow of control from a generic framework. A software architecture with this design inverts control as compared to traditional procedural programming: in traditional programming, the custom code that expresses the purpose of the program calls into reusable libraries to take care of generic tasks, but with inversion of control, it is the framework that calls into the custom, or task-specific, code. 来源:https://en.wikipedia.org/wiki/Inversion_of_control

(在软件工程中,控制反转(IoC)是一种编程原理。IoC反转的流程与传统控制流程相比。在IoC中,计算机程序中自定义编写的部分从通用框架接收控制流。采用这种设计的软件体系结构是颠倒的控件与传统过程式编程相比:在传统编程中,自定义表示程序调用可重用库的目的的代码,以处理泛型任务,但是由于控制反转,框架调用定制的,或者特定于任务的代码)

 

IoC发展简介

  • IoC的简史

1)、1983年,Richard E. Sweet 在《The Mesa Programming Environment》中提出“Hollywood Principle”(好莱坞原则)
2)、1988年,Ralph E. Johnson & Brian Foote 在《Designing Reusable Classes》中提出“Inversion of control”(控制反转)
3)、1996年,Michael Mattsson 在《Object-Oriented Frameworks, A survey of methodological issues》中将“Inversion of control”命名为 “Hollywood principle”
4)、2004年,Martin Fowler 在《Inversion of Control Containers and the Dependency Injection pattern》中提出了自己对 IoC 以及 DI 的理解
5)、2005年,Martin Fowler 在 《InversionOfControl》对 IoC 做出进一步的说明

Implementation techniques 小节的定义:
“ In object-oriented programming, there are several basic techniques to implement inversion of control. These are:
• Using a service locator pattern
• Using dependency injection, for example
Constructor injection
Parameter injection
Setter injection
Interface injection
• Using a contextualized lookup
• Using template method design pattern
• Using strategy design pattern

 

IoC主要实现策略

《Expert One-on-One™ J2EE™ Development without EJB™》提到的主要实现策略 : “IoC is a broad concept that can be implemented in different ways. There are two main types:

  • Dependency Lookup: The container provides callbacks to components, and a lookup context. This is the EJB and Apache Avalon approach. It leaves the onus on each component to use container APIs to look up resources and collaborators. The Inversion of Control is limited to the container invoking callback methods that application code can use to obtain resources.
  •  Dependency Injection: Components do no look up; they provide plain Java methods enabling the container to resolve dependencies. The container is wholly responsible for wiring up components, passing resolved objects in to JavaBean properties or constructors. Use of JavaBean properties is called Setter Injection; use of constructor arguments is called Constructor Injection.”

 

IoC容器的职责

在 Overview 小节中提到:
“Inversion of control serves the following design purposes:
• To decouple the execution of a task from implementation.
• To focus a module on the task it is designed for.
• To free modules from assumptions about how other systems do what they do and instead rely on contracts.
• To prevent side effects when replacing a module.
Inversion of control is sometimes facetiously referred to as the "Hollywood Principle: Don't call us, we'll call you".”(好莱坞原则:你不要来找我,我会去找你)

  • 通用职责

  • 依赖处理
    依赖查找
    依赖注入

  • 生命周期管理
    容器
    托管的资源(Java Beans 或其他资源)

  • 配置
    容器
    外部化配置
    托管的资源(Java Beans 或者其他资源)

 

IoC容器的实现

 

传统IoC容器的实现

 

轻量级IoC容器

《Expert One-on-One™ J2EE™ Development without EJB™》认为轻量级容器的特征 :“

• A container that can manage application code.(可以管理应用程序代码的容器)
• A container that is quick to start up.(快速启动的容器)
• A container that doesn't require any special deployment steps to deploy objects within it.(不需要任何特殊部署步骤就可以在其中部署对象的容器)
• A container that has such a light footprint and minimal API dependencies that it can be run in a variety of environments.(一个占用空间小,API依赖性最小的容器,它可以在各种环境中运行)
• A container that sets the bar for adding a managed object so low in terms of deployment effort and performance overhead that it's possible to deploy and manage fine-grained objects, as well as coarse-grained components.”(在部署工作量和性能开销方面设置非常低的添加托管对象的工具条的容器,以至于可以部署和管理细粒度的对象以及粗粒度的组件)

《Expert One-on-One™ J2EE™ Development without EJB™》认为轻量级容器的好处

• Escaping the monolithic container(逃离单片容器)
• Maximizing code reusability(最大化代码的可重用性)
• Greater object orientation(更大的面向对象)
• Greater productivity(更大的生产力)
• Better testability(更好的可测试性)

 

依赖查找 VS 依赖注入

  • Spring Framework 对构造器注入与 Setter 的论点

“ The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null. Furthermore, constructor-injected components are always returned to the client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.
(Spring团队通常提倡构造函数注入,因为它允许您将应用程序组件实现为不可变的对象,并确保所需的依赖项不是null。此外,注入构造函数的组件总是以完全初始化的状态返回给客户机(调用)代码。顺便提一下,大量的构造函数参数是一种不好的代码味道,这意味着类可能有太多的责任,应该重构它们,以便更好地处理关注点的适当分离)

Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection. ”
(Setter注入主要应该只用于可选的依赖项,这些依赖项可以在类中分配合理的默认值。否则,在代码使用依赖项的任何地方都必须执行非空检查。setter注入的一个好处是,setter方法使该类的对象可以稍后重新配置或重新注入。因此,通过JMX mbean进行管理是setter注入的一个引人注目的例)

  • 《Expert One-on-One™ J2EE™ Development without EJB™》认为 Setter 注入的优点 :

“ Advantages of Setter Injection include:
• JavaBean properties are well supported in IDEs.
• JavaBean properties are self-documenting.
• JavaBean properties are inherited by subclasses without the need for any code.
• It's possible to use the standard JavaBeans property-editor machinery for type conversions if necessary.
• Many existing JavaBeans can be used within a JavaBean-oriented IoC container without modification.
• If there is a corresponding getter for each setter (making the property readable, as well as writable), it is possible to ask the component for its current configuration state. This is particularly useful if we want to persist that state: for example, in an XML form or in a database. With Constructor Injection, there's no way to find the current state.
• Setter Injection works well for objects that have default values, meaning that not all properties need to be supplied atruntime. ”
(Setter注入的优点包括:
•JavaBean属性在ide中得到了很好的支持
•JavaBean属性是自文档化的
•JavaBean属性由子类继承,不需要任何代码
•如果需要,可以使用标准javabean属性编辑器机制进行类型转换
•许多现有的javabean可以在一个面向javabean的IoC容器中使用,而无需修改
•如果每个setter都有相应的getter(使属性可读,也可写),则可以请求组件的当前配置状态。如果我们想要保持这种状态,这是特别有用的:例如,在XML表单或数据库中。使用构造函数注入,就无法找到当前状态
•Setter注入对于具有默认值的对象很有效,这意味着不需要提供所有属性运行时)

  • 《Expert One-on-One™ J2EE™ Development without EJB™》认为 Setter 注入的缺点 :

“ Disadvantages include:
The order in which setters are called is not expressed in any contract. Thus, we sometimes need to invoke a method after the last setter has been called to initialize the component. Spring provides the org.springframework.beans.factory.InitializingBean interface for this; it also provides the ability to invoke an arbitrary init method. However, this contract must be documented to ensure correct use outside a container.
Not all the necessary setters may have been called before use. The object can thus be left partially configured. ”
(缺点包括:
调用setter的顺序在任何契约中都没有表示。因此,我们有时需要在调用最后一个setter后调用方法来初始化组件。Spring提供了org.springframe .bean .factory.InitializingBean接口;它还提供了调用任意init方法的能力。然而,该合同必须形成文件,以确保在容器外正确使用。并非所有必需的setter可能在使用之前都已被调用。因此,可以保留对象的部分配置)

  • 《Expert One-on-One™ J2EE™ Development without EJB™》认为构造器注入的优点:

“ Advantages of Constructor Injection include:
Each managed object is guaranteed to be in a consistent state—fully configured—before it can be invoked in any business methods. This is the primary motivation of Constructor Injection. (However, it is possible to achieve the same result with JavaBeans via dependency checking, as Spring can optionally perform.) There's no need for initialization methods.
There may be slightly less code than results from the use of multiple JavaBean methods, although will be no difference in complexity. ”
(构造函数注入的优点包括:
在任何业务方法中调用之前,保证每个托管对象处于一致的状态全配置状态。这是构造函数注入的主要动机。(然而,通过依赖项检查,可以用javabean实现相同的结果,Spring可以有选择地执行。)不需要初始化方法。与使用多种JavaBean方法的结果相比,代码可能稍微少一些,但是在复杂性上没有什么区别)

  • 《Expert One-on-One™ J2EE™ Development without EJB™》认为构造器注入的缺点:

“ Disadvantages include:
• Although also a Java-language feature, multi-argument constructors are probably less common in existing code than use of JavaBean properties.
• Java constructor arguments don't have names visible by introspection.
• Constructor argument lists are less well supported by IDEs than JavaBean setter methods.
• Long constructor argument lists and large constructor bodies can become unwieldy.
• Concrete inheritance can become problematic.
• Poor support for optional properties, compared to JavaBeans
• Unit testing can be slightly more difficult
• When collaborators are passed in on object construction, it becomes impossible to change the reference held in the object. ”
(•尽管也是java语言的特性,但是在现有代码中,多参数构造函数可能不如使用JavaBean属性常见
•Java构造函数参数没有内省可见的名称
•ide对构造函数参数列表的支持不如JavaBean setter方法好
•长构造函数参数列表和大型构造函数主体可能变得笨拙
•具体的继承可能会有问题
•与javabean相比,对可选属性的支持较差
•单元测试可能稍微有些困难
•当合作者被传递到对象构造时,就不可能改变对象中的引用)

 

什么是IoC?

简单地说,IoC 是反转控制,类似于好莱坞原则,主要有依赖查找和依赖注入实现

 

依赖查找和依赖注入的区别?

依赖查找是主动或手动的依赖查找方式,通常需要依赖容器或标准 API实现。而依赖注入则是手动或自动依赖绑定的方式,无需依赖特定的容器和API

 

Spring 作为IoC容器有什么优势?

典型的IoC管理,依赖查找和依赖注入
AOP抽象
事务抽象
事务机制
SPI机制
强大的第三方整合
易测试性
更好的面向对象

 

Spring IoC依赖查找

  • 根据Bean名称查找
    实时查找
    延时查找

  • 根据Bean类型查找
    单个Bean 对象
    集合Bean 对象

  • 根据Bean名称 + 类型查找

  • 根据Java注解查找
    单个Bean 对象
    集合Bean 对象

 

Spring IoC依赖注入

  • 根据Bean名称注入

  • 根据Bean 类型注入
    单个Bean对象
    集合Bean 对象

  • 注入容器内建Bean对象

  • 注入非Bean对象

  • 注入类型
    实时注入
    延迟注入

 

Spring IoC 依赖来源

  • 自定义Bean

  • 容器内建Bean对象

  • 容器内建依赖

 

Spring IoC配置元信息

  • Bean 定义配置
    基于XML文件
    基于Properties文件
    基于Java注解
    基于Java API

  • IoC容器配置
    基于XML文件
    基于Java注解
    基于Java API

  • 外部化属性配置
    基于Java 注解

 

BeanFactory 和 ApplicationContext 谁才是 Spring IoC 容器?

  • BeanFactory 是 Spring 底层 IoC 容器
  • ApplicationContext 是具备应用特性的 BeanFactory 超集

 

Spring 应用上下文

ApplicationContext 除了 IoC 容器角色,还有提供:

面向切面(AOP)
配置元信息(Configuration Metadata)
资源管理(Resources)
事件(Events)
国际化(i18n)
注解(Annotations)
Envirnment抽象(Environment Abstraction)
https://docs.spring.io/spring/docs/5.2.2.RELEASE/spring-framework-reference/core.html#beans-introduction

 

Spring IoC 容器生命周期

  • 启动

  • 运行

  • 停止

 

什么是Spring IoC容器?

Spring Framework implementation of the Inversion of Control (IoC) principle. IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean.
(实现了Spring框架的反转控制(IoC)原则。IoC也称为依赖注入(dependency injection, DI)。在这个过程中,对象只通过构造函数参数、工厂方法的参数或对象实例构造或从工厂方法返回后在对象实例上设置的属性来定义它们的依赖项(即它们所使用的其他对象)。然后容器在创建bean时注入这些依赖项)

 

BeanFactory 与 FactoryBean 的区别?

BeanFactory 是 IoC 底层容器
FactoryBean 是 创建 Bean 的一种方式,帮助实现复杂的初始化逻辑

 

Spring IoC容器启动时做了哪些准备?

IoC 配置元信息读取和解析、IoC容器生命周期、Spring 事件发布、国际化等

 

定义Spring Bean

什么是BeanDefinition?

BeanDefinition 是 Spring Framework 中定义 Bean 的配置元信息接口,包含:
1、Bean 的类名
2、Bean 行为配置元素,如作用域、自动绑定的模式、生命周期回调等
3、其他Bean应用,又可称作合作者(collaborators)或者依赖(dependencies)
4、配置设置,比如Bean 属性(Properties)

 

BeanDefinition 元信息

属性(Property)说明
ClassBean 全类名,必须是具体类,不能用抽象类或接口
NameBean 的名称或者ID
ScopeBean 的作用域(如:singleton、prototype等)
Constructor argumentsBean 构造器参数(用依赖注入)
PropertiesBean 属性设置(用于依赖注入)
Autowiring modeBean 自动绑定模式(如:通过名称byName)
Lazy initialzation modeBean 延迟初始化模式(延迟和非延迟)
initialization methodBean 初始化回调方法名称
Destruction methodBean 销毁回调方法名称

 

BeanDefinition 构建

  • 通过BeanDefinitionBuilder

  • 通过AbstractBeanDefinition 以及 派生类

 

命名Spring Bean

  • Bean 的名称

每个 Bean 拥有一个或多个标识符(identifiers),这些标识符在 Bean 所在的容器必须是唯一的。通常,一个 Bean 仅有一个标识符,如果需要额外的,可考虑使用别名(Alias)来扩充

在基于 XML 的配置元信息中,开发人员可用 id 或者 name 属性来规定 Bean 的 标识符。通常Bean 的 标识符由字母组成,允许出现特殊字符。如果要想引入 Bean 的别名的话,可在name 属性使用半角逗号(“,”)或分号(“;”) 来间隔

Bean 的 id 或 name 属性并非必须制定,如果留空的话,容器会为 Bean 自动生成一个唯一的名称。Bean 的命名尽管没有限制,不过官方建议采用驼峰的方式,更符合 Java 的命名约定

  • Bean 名称生成器(BeanNameGenerator)

由 Spring Framework 2.0.3 引入,框架內建两种实现:

  • DefaultBeanNameGenerator:默认通用 BeanNameGenerator 实现
  • AnnotationBeanNameGenerator:基于注解扫描的 BeanNameGenerator 实现,起始于Spring Framework 2.5,关联的官方文档:

With component scanning in the classpath, Spring generates bean names for unnamed components,following the rules described earlier: essentially, taking the simple class name and turning its initial character to lower-case. However, in the (unusual) special case when there is more than one character and both the first and second characters are upper case, the original casing gets preserved. These are the same rules as defined by java.beans.Introspector.decapitalize (which Spring uses here).

 

Spring Bean 的别名

Bean 别名(Alias)的价值:

  • 复用现有的 BeanDefinition
  • 更具有场景化的命名方法,比如:

<alias name="myApp-dataSource" alias="subsystemA-dataSource"/>
<alias name="myApp-dataSource" alias="subsystemB-dataSource"/>

 

注册Spring Bean

  • BeanDefinition 注册
    XML配置元信息
    <bean name=”...” ... />

    Java 注解配置元信息
    @Bean
    @Component
    @Import

    Java API 配置元信息
    命名方式:BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)

    非命名方式:BeanDefinitionReaderUtils#registerWithGeneratedName(AbstractBeanDefinition,BeanDefinitionRegistry)

    配置类方式:AnnotatedBeanDefinitionReader#register(Class...)

  • 外部单体对象注册
    Java API配置元信息  SingletonBeanRegistry#registerSingleton

 

实例化(Instantiation)Spring Bean

  • 常规方式
    通过构造器(配置元信息:XML、Java 注解 和 Java API)
    通过静态工厂方法(配置元信息:XML、Java API)
    通过Bean工厂方法(配置元信息:XML、Java API)
    通过FactoryBean(配置元信息:XML、Java 注解 和 Java API)

  • 特殊方式
    通过 ServiceLoaderFactoryBean(配置元信息:XML、Java 注解和 Java API )
    通过 AutowireCapableBeanFactory#createBean(java.lang.Class, int, boolean)
    通过 BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)

 

初始化(Initialization)Spring Bean

  • @PostConstruct 标注方法

  • 实现InitializingBean 接口的afterPropertiesSet() 方法

  • 自定义初始化方法
    XML配置:<bean init-method=”init” ... />
    Java注解:@Bean(initMethod=”init”)
    Java API:AbstractBeanDefinition#setInitMethodName(String)

假设以上三种方式均在同一 Bean 中定义,那么这些方法的执行顺序是:从上到下依次执行

 

延迟初始化 Spring Bean

Bean 延迟初始化(Lazy Initialization)

  • XML配置:<bean lazy-init=”true” ... />
  • Java 注解:@Lazy(value = true)

 

销毁Spring Bean

Bean 销毁(Destroy)

  • @PreDestroy 标注方法

  • 实现DisposableBean 接口的destroy() 方法

  • 自定义销毁方法
    XML配置:<bean destroy=”destroy” ... />
    Java 注解:@Bean(destroy=”destroy”)
    Java API:AbstractBeanDefinition#setDestroyMethodName(String)

 

垃圾回收Spring Bean

Bean 垃圾回收(GC)
1、关闭Spring 容器(应用上下文)
2、执行GC
3、Spring Bean 覆盖的finalized()方法被回调

 

单一类型依赖查找

单一类型依赖查找接口 - BeanFactory

  • 根据Bean 名称查找
    getBean(String)
    Spring 2.5 覆盖默认参数:getBean(String,Object...)

  • 根据Bean类型查找
    Bean 实时查找
    Spring 3.0 getBean(Class)
    Spring 4.1 覆盖默认参数:getBean(String,Object.....)

    Spring5.1 Bean 延迟查找
    getBeanProvider(Class)
    getBeanProvider(ResolvableType)

  • 根据Bean 名称 + 类型查找:getBean(String,Class)

 

集合类型依赖查找

集合类型依赖查找接口 - ListableBeanFactory

  • 根据Bean 类型查找
    获取同类型Bean 名称列表
    getBeanNamesForType(Class)
    Spring 4.2 getBeanNamesForType(ResolvableType)

    获取同类型Bean 实例列表
    getBeansOfType(Class) 以及重载方法

  • 通过注解类型查找
    Spring 3.0 获取标注类型Bean 名称列表
    getBeanNamesForAnnotation(Class<? extends Annotation>)

    Spring 3.0 获取标注类型 Bean 实例列表
    getBeansWithAnnotation(Class<? extends Annontation>)

    Spring 3.0 获取指定名称 + 标注类型 Bean 实例
    findAnnotationOnBean(String,Class<? extends Annotation>)

 

层次性依赖查找

  • 双亲BeanFactory:getParentBeanFactory()

  • 层次性查找
    根据Bean名称查找
    基于containsLocalBean方法实现

    根据Bean类型查找实例列表
    单一类型:BeanFactoryUtils#beanOfType
    集合类型:BeanFactoryUtils#beansOfTypeIncludingAncestors

    根据Java注解查找名称列表
    BeanFactoryUtils#beanNamesForTypeIncludingAncestors

 

延迟依赖查找

Bean 延迟依赖查找接口

  • org.springframework.beans.factory.ObjectFactory

  • org.springframework.beans.factory.ObjectProvider
    Spring 5 对Java 8 特性扩展
    函数式接口
    getIfAvailable(Supplier)
    ifAvailable(Consumer)
    Stream 扩展stream()

 

安全依赖查找对比

依赖查找类型代表实现是否安全
单一类型查找BeanFactory#getBean
 ObjectFactory#getObject
 ObjectProvider#getIfAvailable
   
集合类型查找ListableBeanFactory#getBeansOfType
 ObjectProvider#stream

层次性依赖查找的安全性取决于其扩展的单一或集合类型的BeanFactory接口

 

内建可查找的依赖

  • AbstractApplicationContext 内建可查找的依赖
Bean 名称Bean 实例使用场景
environmentEnvironment 对象外部化配置以及 Profiles
systemPropertiesjava.util.Properties对象Java 系统属性
systemEnvironmentjava.util.Map 对象操作系统环境变量
messageSourceMessageSource 对象国际化文案
lifecycleProcessorLifecycleProcessor 对象Lifecycle Bean 处理器
applicationEventMulticasterApplicationEventMulticaster 对象Spring 事件广播器
  • 注解驱动 Spring 应用上下文内建可查找的依赖
Bean 名称Bean 实例使用场景
org.springframework.context.annotation.internalConfigurationAnnotationProcessorConfigurationClassPostProcessor 对象处理 Spring 配置类
org.springframework.context.annotation.internalAutowiredAnnotationProcessorAutowiredAnnotationBeanPostProcessor 对象处理 @Autowired 以及 @Value 注解
org.springframework.context.annotation.internalCommonAnnotationProcessorCommonAnnotationBeanPostProcessor 对象(条件激活)处理JSR-250注解,如 @PostConstruct 等
org.springframework.context.event.internalEventListenerProcessorEventListenerMethodProcessor 对象处理标注@EventListener 的Spring 事件监听方法
org.springframework.context.event.internalEventListenerFactoryDefaultEventListenerFactory 对象@EventListener事件监听方法适配为ApplicationListener
org.springframework.context.annotation.internalPersistenceAnnotationProcessorPersistenceAnnotationBeanPostProcessor 对象(条件激活)处理 JPA 注解场景

 

依赖查找中的经典异常

  • BeansException 子类型
异常类型触发条件(举例)场景举例
NoSuchBeanDefinitionException当查找Bean不存在于IoC容器时

BeanFactory#getBean

ObjectFactory#getObject

NoUniqueBeanDefinitionException类型依赖查找时,IoC容器存在多个Bean实例BeanFactory#getBean(Class)
BeanInstantiationException当Bean 所对应的类型非具体类时BeanFactory#getBean
BeanCreationException当 Bean 初始化过程中Bean初始化方法执行异常
BeanDefinitionStoreException当BeanDefinition配置元信息非法时XML 配置资源无法打开时

 

ObjectFactory 与 BeanFactory 的区别?

ObjectFactory 与 BeanFactory 均提供依赖查找的能力

不过 ObjectFactory 仅关注一个或一种类型的 Bean 依赖查找,并且自身不具备依赖查找的能力,能力则由 BeanFactory 输出

BeanFactory 则提供了单一类型、集合类型以及层次性等多种依赖查找方式

 

BeanFactory.getBean 操作是否线程安全?

BeanFactory.getBean 方法的执行是线程安全的,超过过程中会增加互斥锁

 

依赖注入的模式和类型

  • 手动模式 - 配置或者编程的方式,提前安排注入规则
    XML 资源配置元信息
    Java 注解配置元信息
    API配置元信息

  • 自动模式 - 实现方提供依赖自动关联的方式,按照内建的注入规则
    Autowiring(自动绑定)

依赖注入类型配置元数据举例
Setter 方法<property name="user" ref="userBean"/>
构造器<constructor-arg name="user" ref="userBean"/>
字段

@Autowired User user;

方法@Autowired public void user(User user){...}
接口回调class MyBean implements BeanFactoryAware{....}

 

自动绑定(Autowiring)

  • 官方说明:
    The Spring container can autowire relationships between collaborating beans. You can let Spring resolve collaborators (other beans) automatically for your bean by inspecting the contents of the ApplicationContext.
    (Spring容器可以自动连接协作bean之间的关系。通过检查ApplicationContext的内容,您可以让Spring自动地为您的bean解析协作者(其他bean))

  • 优点:
    • Autowiring can significantly reduce the need to specify properties or constructor arguments.
    • Autowiring can update a configuration as your objects evolve.
    (•自动装配可以显著减少指定属性或构造函数参数的需要
        •自动装配可以随着对象的演进更新配置)

 

自动绑定(Autowiring)模式

  • Autowiring modes
模式说明
no默认值,未激活Autowiring,需要手动指定依赖注入对象
byName根据被注入属性的名称作为Bean名称进行依赖查找,并将对象设置到该属性
byType根据被注入属性的类型作为依赖类型进行查找,并将对象设置到该属性
constructor特殊 byType 类型,用于构造器参数
  • 限制和不足

https://docs.spring.io/spring/docs/5.2.2.RELEASE/spring-framework-reference/core.html#beans-autowired-exceptions

 

Setter 方法注入

实现方式

  • 手动模式
    XML资源配置元信息
    Java 注解配置元信息
    API配置元信息

  • 自动模式
    byName
    byType

 

构造器注入

实现方式

  • 手动模式
    XML 资源配置元信息
    Java 注解配置元信息
    API 配置元信息

  • 自动模式
    constructor

 

字段注入

实现方式

  • 手动模式

      Java 注解配置元信息
   @Autowired
   @Resource
   @Inject(可选)

 

方法注入

实现方式

  • 手动模式

      Java 注解配置元信息
   @Autowired
   @Resource
   @Inject(可选)
   @Bean

 

接口回调注入

Aware 系列接口回调

  • 自动模式
内建接口说明
BeanFactoryAware获取IoC容器 - BeanFactory
ApplicationContextAware获取Spring 应用上下文 - ApplicationContext 对象
EnvironmentAware获取 Environment 对象
ResourceLoaderAware获取资源加载器对象 - ResourceLoader
BeanClassLoaderAware获取加载当前 Bean Class 的ClassLoader
BeanNameAware获取当前Bean的名称
MessageSourceAware获取MessageSource对象,用于Spring 国际化
ApplicationEventPublisherAware获取ApplicationEventPublishAware对象,用于Spring 事件
EmbeddedValueResolverAware获取StringValueResolver对象,用于占位符处理

 

依赖注入类型选择

  • 注入选型
  • 低依赖:构造器注入

  • 多依赖:Setter 方法注入

  • 便利性:字段注入

  • 声明类:方法注入

 

基础类型注入

  • 原生类型(Primitive):boolean、byte、char、short、int、float、long、double

  • 标量类型(Scalar):Number、Character、Boolean、Enum、Locale、Charset、Currency、Properties、UUID

  • 常规类型(General):Object、String、TimeZone、Calendar、Optional等

  • Spring 类型:Resource、InputSource、Formatter等

 

集合类型注入

  • 数组类型(Array):原生类型、标量类型、常规类型、Spring类型

  • 集合类型(Collection)
    Collection:List、Set(SortedSet、NavigableSet、EnumSet)
    Map:Properties

 

限定注入

  • 使用注解 @Qualifier 限定
    通过 Bean 名称限定
    通过分组限定

  • 基于注解@Qualifier 扩展限定
    自定义注解 - 如 Spring Cloud @LoadBalanced

 

延迟依赖注入

  • 使用 API ObjectFactory 延迟注入
    单一类型
    集合类型

  • 使用API ObjectProvider 延迟注入(推荐)
    单一类型
    集合类型

 

依赖处理过程

  • 入口 - DefaultListableBeanFactory#resolveDependency

  • 依赖描述符 - DependencyDescriptor

  • 自动绑定候选对象处理器 - AutowireCandidateResolver

 

@Autowired 注入

@Autowired 注入规则

  • 非静态字段

  • 非静态方法

  • 构造器

@Autowired 注入过程

  • 元信息解析

  • 依赖查找

  • 依赖注入(字段、方法)

 

@Inject 注入

@Inject 注入过程
如果 JSR-330 存在于 ClassPath 中,复用 AutowiredAnnotationBeanPostProcessor 实现

 

Java 通用注解注入原理

CommonAnnotationBeanPostProcessor

  • 注入注解
javax.xml.ws.WebSerivceRef
javax.ejb.EJB
javax.annotation.Resource
  • 生命周期注解
javax.annotation.PostConstruct
javax.annotation.PreDestroy

 

自定义依赖注入注解

  • 基于 AutowiredAnnotationBeanPostProcesser  实现
  • 自定义实现

生命周期处理
InstantiationAwareBeanPostProcessor
MergedBeanDefinitionPostProcessor

元数据
InjectedElement
InjectionMetadata

 

有多少种依赖注入的方式?

构造器注入、Setter 注入、字段注入、方法注入、接口回调注入

 

你偏好构造器注入还是Setter 注入?

两种依赖注入的方式均可使用,如果是必须依赖的话,那么推荐使用构造器注入,Setter 注入用于可选依赖

 

Spring 依赖注入的来源有哪些?

Spring BeanDefinition、单体对象、Resolvable Dependency、@Value 外部化配置

 

依赖查找的来源

  • 查找来源
来源配置元数据
Spring BeanDefinition<bean id="user" class="org.vincent.User"/>
 @Bean public User user(){....}
 BeanDefinitionBuilder
单体对象API 实现
  • Spring 内建 BeanDefinition
Bean 名称Bean 实例使用场景
org.springframework.context.annotation.internalConfigurationAnnotationProcessorConfigurationClassPostProcessor对象处理Spring 配置类
org.springframework.context.annotation.internalAutowiredAnnotationProcessorAutowiredAnnotationBeanPostProcessor 对象处理@Autowired 以及@Value注解
org.springframework.context.annotation.internalCommonAnnotationProcessorCommonAnnotationBeanPostProcessor对象(条件激活)处理JSR-250注解,如 @PostConstruct 等
org.springframework.context.internalEventListenerProcessorEventListenerMethodProcessor 对象处理标注@EventListener的Spring 事件监听方法
  • Spring 内建单例对象
Bean 名称Bean 实例使用场景
environmentEnvironment 对象外部化配置以及 Profiles
systemPropertiesjava.util.Properties 对象Java 系统属性
systemEnvironmentjava.util.Map 对象操作系统环境变量
messageSourceMessageSource 对象国际化文案
lifecycleProcessorLifecycleProcessor 对象Lifecycle Bean 处理器
applicationEventMulticasterApplicationEventMulticaster 对象Spring 事件广播器

 

依赖注入的来源

  • 注入来源
来源配置元数据
Spring BeanDefinition<bean id="user" class="org.vincent.User"/>
 @Bean public User user(){....}
 BeanDefinitionBuilder
单例对象API实现
非 Spring 容器管理对象 

 

Spring 容器管理和游离对象

  • 依赖对象
来源Spring Bean 对象生命周期管理配置元信息使用场景
Spring BeanDefinition依赖查找、依赖注入
单体对象依赖查找、依赖注入
Resolvable Dependency依赖注入

 

Spring BeanDefinition 作为依赖来源

  • 元素

1、元数据:BeanDefinition
2、注册:BeanDefinitionRegistry#registerBeanDefinition
3、类型:延迟和非延迟
4、顺序:Bean 生命周期顺序按照注册顺序

 

单例对象作为依赖来源

  • 要素
    来源:外部普通Java对象(不一定是POJO)
    注册:SingletonBeanRegistry#registerSingleton

  • 限制
    无生命周期管理
    无法实现延迟初始化Bean

 

非Spring 容器管理对象作为依赖来源

  • 要素
    注册:ConfigurableListableBeanFactory#registerResolvableDependency

  • 限制
    无生命周期管理
    无法实现延迟初始化Bean
    无法通过依赖查找

 

外部化配置作为依赖来源

  • 要素
    类型:非常规 Spring 对象依赖来源

  • 限制
    无生命周期管理
    无法实现延迟初始化Bean
    无法通过依赖查找

 

注入和查找的依赖来源是否相同?

否,依赖查找的来源仅限于Spring BeanDefinition 以及单例对象,而依赖注入的来源还包括Resolvable Dependency以及 @Value 所标注的外部化配置

 

单例对象能在IoC容器启动后注册吗?

可以的,单例对象的注册与BeanDefinition 不同,BeanDefinition 会被 ConfinurableListableBeanFactory#freezeConfiguration() 方法影响,从而冻结注册,单例对象则没有这个限制

 

Spring Bean 作用域

来源说明
singleton默认Spring Bean作用域,一个BeanFactory 有且仅有一个实例
prototype原型作用域,每次依赖查找和依赖注入生成新 Bean 对象
request将 Spring Bean 存储在 ServletRequest 上下文中
session将 Spring Bean 存储在 HttpSession 中
application将 Spring Bean 存储在 ServletContext 中

 

 

“singleton” Bean 作用域

 

“prototype” Bean 作用域

  • 注意事项

Spring 容器没有办法管理 prototype Bean 的完整生命周期,也没有办法记录示例的存在。销毁回调方法将不会执行,可以利用BeanPostProcessor 进行清扫工作

 

"request" Bean 作用域

  • 配置
    XML - <bean class= "..." scope = "request" />
    Java 注解 - @RequestScope 或 @Scope (WebApplicationContext.SCOPE_REQUEST)

  • 实现
    API - RequestScope

 

"session" Bean 作用域

  • 配置
    XML - <bean class= "..." scope = "session" />
    Java注解 - @RequestScope 或 @Scope (WebApplication.SCOPE_SESSION)

  • 实现
    API - SessionScope

 

"application" Bean 作用域

  • 配置
    XML - <bean class= "..." scope = "application" />
    Java 注解 - @ApplicationScope 或 @Scope(WebApplicationContext.SCOPE_APPLICATION)

  • 实现
    API - ApplicationScope

 

自定义 Bean 作用域

  • 实现Scope
    org.springframework.beans.factory.config.Scope

  • 注册Scope
    API - org.springframework.beans.factory.config.ConfigurableBeanFactory#registerScope
    配置

    <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
       <property name="scopes">
           <map>
               <entry key="...">
               </entry>
           </map>
       </property>
    </bean>

     

 

Spring 内建的Bean 作用域有几种?

singleton 、prototype、request、session、application 以及 websocket

 

singleton Bean 是否在一个应用是唯一的?

否,singleton bean 仅在当前Spring IoC 容器(BeanFactory)中是单例对象

 

“application” Bean 是否被其他方案替代?

可以的,实际上,“application” Bean 与 “singleton” Bean 没有本质区别

 

Spring Bean 元信息配置阶段

  • BeanDefinition 配置

1、面向资源
      XML 配置
      Properties 资源配置

2、面向注解

3、面向API

 

Spring Bean 元信息解析阶段

  • 面向资源BeanDefinition 解析
    BeanDefinitionReader
    XML解析器 - BeanDefinitionParser

  • 面向注解BeanDefinition 解析
    AnnotatedBeanDefinitionReader

 

Spring Bean 注册阶段

  • BeanDefinition 注册接口

BeanDefinitionRegistry

 

Spring BeanDefinition 合并阶段

  • BeanDefinition 合并

       父子BeanDefinition 合并
       1、当前BeanFactory 查找
       2、层次性BeanFactory查找

 

Spring Bean Class 加载阶段

  • ClassLoader 类加载

  • Java Security 安全控制

  • ConfigurableBeanFactory 临时 ClassLoader

 

Spring Bean 实例化阶段

实例化方式

  • 传统实例化方式
    实例化策略 - InstantiationStrategy

  • 构造器依赖注入

 

Spring Bean 实例化前阶段

  • 非主流生命周期 - Bean 实例化前阶段

InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation

 

Spring Bean 实例化后阶段

  • Bean 属性赋值(Populate) 判断

InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation

 

Spring Bean 属性赋值前阶段

  • Bean 属性值元信息
    PropertyValues

  • Bean 属性赋值前回调
    Spring 1.2 - 5.0:InstantiationAwareBeanPostProcessor#postProcessPropertyValues
    Spring 5.1:InstantiationAwareBeanPostProcessor#postProcessProperties

 

Spring Bean Aware 接口回调阶段

Spring Aware接口

  • BeanNameAware
  • BeanClassLoaderAware
  • BeanFactoryAware
  • EnvironmentAware
  • EmbeddedValueResolverAware
  • ResourceLoaderAware
  • ApplicationEventPublisherAware
  • MessageSourceAware
  • ApplicationContextAware

 

Spring Bean 初始化前阶段

  • 已完成
    Bean 实例化
    Bean 属性赋值
    Bean Aware 接口回调

  • 方法回调
    BeanPostProcessor#postProcessBeforeInitialization

 

Spring Bean 初始化阶段

Bean 初始化(Initialization)

  • @PostConstruct 标注方法

  • 实现InitializingBean 接口的 afterPropertiesSet() 方法

  • 自定义初始化方法

 

Spring Bean 初始化后阶段

  • 方法回调

BeanPostProcessor#postProcessAfterInitialization

 

Spring Bean 初始化完成阶段

  • 方法回调

Spring 4.1 +:SmartInitializingSingleton#afterSingletonsInstantiated

 

Spring Bean 销毁前阶段

  • 方法回调

DestructionAwareBeanPostProcessor#postProcessBeforeDestruction

 

Spring Bean 销毁阶段

Bean 销毁(Destroy)

  • @PreDestroy 标注方法

  • 实现DisposableBean 接口的destroy() 方法

  • 自定义销毁方法

 

Spring Bean 垃圾收集

Bean 垃圾回收(GC)

  • 关闭Spring 容器(应用上下文)

  • 执行GC

  • Spring Bean 覆盖的finalize() 方法被回调

 

BeanPostProcessor 的使用场景有哪些?

BeanPostProcessor 提供Spring Bean 初始化前和初始化后的生命周期回调,分别对应postProcessBeforeInitialization 以及 postProcessAfterInitialization 方法,允许对关心的Bean 进行扩展,甚至是替换。
其中,ApplicationContext 相关的Aware 回调也是基于BeanPostProcessor 实现,即ApplicationContextAwareProcessor

 

BeanFactoryPostProcessor 与 BeanPostProcessor 的区别?

BeanFactoryPostProcessor 是 Spring BeanFactory (实际为ConfigurableListableBeanFactory)的后置处理器,用于扩展BeanFactory,或通过BeanFactory进行依赖查找和依赖注入

BeanFactoryPostProcessor 必须有Spring ApplicationContext 执行,BeanFactory 无法与其直接交互

而BeanPostProcessor 则直接与BeanFactory 关联,属于N 对 1 的关系

 

BeanFactory 是怎样处理Bean生命周期?

BeanFactory 的默认实现为:DefaultListableBeanFactory,其中Bean生命周期与方法映射如下:

  • BeanDefinition 注册阶段 - registerBeanDefinition
  • BeanDefinition 合并阶段 - getMergedBeanDefinition
  • Bean 实例化前阶段 - resolveBeforeInstantiation
  • Bean 实例化阶段 - createBeanInstance
  • Bean 实例化后阶段 - populateBean
  • Bean 属性赋值前阶段 - populateBean
  • Bean 属性赋值阶段 - populateBean
  • Bean Aware 接口回调阶段 - initializeBean
  • Bean 初始化前阶段 - initializeBean
  • Bean 初始化阶段 - initializeBean
  • Bean 初始化后阶段 - initializeBean
  • Bean 初始化完成阶段 - preInstantiateSingletons
  • Bean 销毁前阶段 - destroyBean
  • Bean 销毁阶段 - destroyBean

 

Spring 配置元信息

  • Spring Bean 配置元信息 - BeanDefinition

  • Spring Bean 属性元信息 - PropertyValues

  • Spring 容器配置元信息

  • Spring 外部化配置元信息 - PropertySource

  • Spring Profile 元信息 - @Profile

 

Spring Bean 配置元信息

Bean配置元信息 - BeanDefinition

  • GenericBeanDefinition:通用类 BeanDefinition

  • RootBeanDefinititon:无Parent的BeanDefinition 或者合并后 BeanDefinition

  • AnnotatedBeanDefinition:注解标注的BeanDefinition

 

Spring Bean 属性元信息

  • Bean 属性元信息 - PropertyValues
    可修改实现 - MutablePropertyValues
    元素成员 - PropertyValue

  • Bean 属性上下文存储 - AttributeAccessor

  • Bean 元信息元素 - BeanMetadataElement

 

Spring 容器配置元信息

  • Spring XML 配置元信息 - beans 元素相关
Bean 元素属性默认值使用场景
profilenull(留空)Spring Profile 配置值
default-lazy-initdefault当 outter beans "default-lazy-init" 属性存在时,继承该值,否则为"false"
default-mergedefault当 outter beans "default-merge" 属性存在时,继承该值,否则为"false"
default-autowiredefault当 outter beans "default-autowire" 属性存在时,继承该值,否则为"no"
default-autowire-candidatesnull(留空)默认Spring Beans 名称 pattern
default-init-methodnull(留空)默认Spring Beans 自定义初始化方法
default-destroy-methodnull(留空)默认Spring Beans 自定义销毁方法
  • Spring XML 配置元信息 - 应用上下文相关
XML 元素使用场景
<context:annotation-config/>激活 Spring 注解驱动
<context:component-scan/>Spring @Component 以及自定义注解扫描
<context:load-time-weaver/>激活 Spring LoadTimeWeaver
<context:mbean-export/>暴露 Spring Beans 作为 JMX Beans
<context:mbean-server/>将当前平台作为 MBeanServer
<context:property-placeholder/>加载外部化配置资源作为 Spring 属性配置
<context:property-override/>利用外部化配置资源覆盖Spring 属性值

 

基于 XML 资源装载Spring Bean 配置元信息

  • Spring Bean 配置元信息(底层实现 - XmlBeanDefinitionReader
XML 元素使用场景
<beans:beans/>单 XML 资源下的多个Spring Beans 配置
<beans:bean/>单个Spring Bean 定义 (BeanDefinition)配置
<beans:alias/>为 Spring Bean 定义 (BeanDefinition)映射别名
<beans:import/>加载外部Spring XML 配置资源

 

基于Properties 资源装载Spring Bean 配置元信息

  • Spring Bean 配置元信息(底层实现 - PropertiesBeanDefinitionReader
Properties 属性名使用场景
(class)Bean 类全称限定名
(abstract)是否为抽象的 BeanDefinition
(parent)指定parent BeanDefinition 名称
(lazy-init)是否为延迟初始化
(ref)引用其他 Bean 的名称
(scope)设置 Bean 的 scope 属性
${n}n 表示第 n + 1 个构造器参数

 

基于Java 注解装载Spring Bean 配置元信息

  • Spring 模式注解
Spring 注解场景说明起始版本
@Repository数据仓储模式注解2.0
@Component通用组件模式注解2.5
@Service服务模式注解2.5
@ControllerWeb 控制器模式注解2.5
@Configuration配置类模式注解3.0
  • Spring Bean 定义注解
Spring 注解场景说明起始版本
@Bean替换 XML 元素<bean>3.0
@DependsOn替换 XML 属性 <bean depends-on="..."/>3.0
@Lazy替换 XML 属性 <bean lazy-init="true|false"/>3.0
@Primary替换 XML 元素 <bean primary="true|false"/>3.0
@Role替换 XML 元素 <bean role="..."/>3.1
@Lookup替换 XML 元素 <bean lookup-method="..."/>4.1
  • Spring Bean 依赖注入注解
Spring 注解场景说明起始版本
@AutowiredBean 依赖注入,支持多种依赖查找方式2.5
@Qualifier细粒度的@Autowired 依赖查找2.5
  • Spring Bean 生命周期回调注解
Spring 注解场景说明起始版本
@PostConstruct替换 XML 元素 <bean init-method="...."> 或 initializingBean2.5
@PreDestroy替换 XML 元素 <bean destroy-method="...."/> 或 DisposableBean2.5

 

Spring Bean 配置元信息底层实现

  • Spring BeanDefinition 解析与注册
实现场景实现类起始版本
XML 资源XmlBeanDefinitionReader1.0
Properties 资源PropertiesBeanDefinitionReader1.0
Java 注解AnnotationBeanDefinitionReader3.0
  • Spring XML 资源 BeanDefinition 解析与注册

核心 API - XmlBeanDefinitionReader
1、资源 - Resource
2、底层 - BeanDefinitionDocumentReader
2.1、XML解析 - Java DOM Level 3 API
2.2、BeanDefinition 解析 - BeanDefinitionParserDelegate
2.3、BeanDefinition 注册 - BeanDefinitionRegistry

  • Spring Properties 资源BeanDefinition 解析与注册

核心 API - PropertiesBeanDefinitionReader
1、资源
1.1、字节流 - Resource
1.2、字符流 - EncodedResource
2、底层
2.1、存储 - java.util.Properties
2.2、BeanDefinition 解析 - API 内部实现
2.3、BeanDefinition 注册 - BeanDefinitionRegistry

  • Spring Java 注解 BeanDefinition 解析与注册

核心 API - AnnotatedBeanDefinitionReader
1、资源
1.1、类对象 - java.lang.Class
2、底层
2.1、条件评估 - ConditionEvaluator
2.2、Bean 范围解析 - ScopeMetadataResolver
2.3、BeanDefinition 解析 - 内部 API 实现
2.4、BeanDefinition 处理 - AnnotationConfigUtils.processCommonDefinitionAnnotations
2.5、BeanDefinition 注册 - BeanDefinitionRegistry

 

基于 XML 资源装载 Spring IoC 容器配置元信息

  • Spring IoC 容器相关XML配置
命名空间所属模块Schema 资源 URL
beansspring-beanshttps://www.springframework.org/schema/beans/spring-beans.xsd
contextspring-contexthttps://www.springframework.org/schema/context/spring-context.xsd
aopspring-aophttps://www.springframework.org/schema/aop/spring-aop.xsd
txspring-txhttps://www.springframework.org/schema/tx/spring-tx.xsd
utilspring-beanshttps://www.springframework.org/schema/util/spring-util.xsd
toolspring-beanshttps://www.springframework.org/schema/tool/spring-tool.xsd

 

基于 Java 注解装载Spring IoC 容器配置元信息

  • Spring IoC 容器装配注解
Spring 注解场景说明起始版本
@ImportResource替换 XML 元素 <import>3.0
@Import导入Configuration Class3.0
@ComponentScan扫描指定 package 下标注 Spring 模式注解的类3.1
  • Spring IoC 配置属性注解
Spring 注解场景说明起始版本
@PropertySource配置属性抽象 PropertySource 注解3.1
@PorpertySources@PropertySource 集合注解4.0

 

基于Extensible XML authoring 扩展 Spring XML 元素

Spring XML 扩展

  • 编写XML Schema 文件:定义XML结构

  • 自定义NamespaceHandler 实现:命名空间绑定

  • 自定义BeanDefinitionParser 实现:XML元素与BeanDefinition 解析

  • 注册XML扩展:命名空间与XML Schema 映射

 

Extensible XML authoring 扩展原理

  • 核心流程

BeanDefinitionParserDelegate#parseCustomElement(org.w3c.dom.Element,BeanDefinition)
1、 获取 namespace
2、通过 namespace 解析 NamespaceHandler
3、构造 ParserContext
4、解析元素,获取 BeanDefinition

 

基于 Properties 资源装载外部化配置

  • 注解驱动
    @org.springframework.context.annotation.PropertySource
    @org.springframework.context.annotation.PropertySources

  • API 编程
    org.springframework.core.env.PropertySource
    org.springframework.core.env.PropertySources

 

基于YAML 资源装载外部化配置

 

Spring 配置元信息具体有哪些?

  • Bean 配置元信息:通过媒介(如XML、Properties等),解析 BeanDefinition

  • IoC 容器配置元信息:通过媒介(如XML、Properties等),控制IoC 容器行为,比如注解驱动、AOP等

  • 外部化配置:通过资源抽象(如Properties、YAML等),控制 PropertySource

  • Spring Profile:通过外部化配置,提供条件分支流程

 

Extensible XML authoring 的缺点?

  • 高度复杂:开发人员需要熟悉XML Schema、spring.handlers、spring.shemas 以及Spring API

  • 嵌套元素支持较弱:通常需要使用方法递归或者嵌套解析的方式处理嵌套(子)元素

  • XML 处理性能较差:Spring XML 基于DOM Level 3 API 实现,该 API 便于理解,然而性能较差

  • XML框架移植性较差:很难适配高性能和便利性的XML 框架,如JAXB

 

Spring 资源管理引入动机

为什么 Spring 不使用 Java 标准资源管理,而选择重新发明轮子?

  • Java 标准资源管理强大,然而扩展复杂,资源存储方式并不统一

  • Spring 要自立门户

  • Spring “抄”、“超”、“潮”

 

Java 标准资源管理

  • Java 标准资源定位
职责说明
面向资源文件系统、artifact(jar 、war 、ear 文件)以及远程资源(HTTP、FTP等)
API 整合java.lang.ClassLoader#getResource、java.io.File 或 java.net.URL
资源定位java.net.URL 或 java.net.URI
面向流式存储java.net.URLConnection
协议扩展java.net.URLStreamHandler 或 java.net.URLStreamHandlerFactory
  • Java URL 协议扩展

基于java.net.URLStreamHandlerFactory

基于java.net.URLStreamHandler

  • 基于 java.net.URLStreamHandlerFactory 扩展协议

  • 基于 java.net.URLStreamHandler 扩展协议

JDK1.8 内建协议实现

协议实现类
filesun.net.www.protocol.file.Handler
ftpsun.net.www.protocol.ftp.Handler
httpsun.net.www.protocol.http.Handler
httpssun.net.www.protocol.https.Handler
jarsun.net.www.protocol.jar.Handler
mailtosun.net.www.protocol.mailto.Handler
netdocsun.net.www.protocol.netdoc.Handler

实现类名必须为“Handler”

实现类命名规则说明
默认sun.net.www.protocol.${protocol}.Handler
自定义通过Java Properties  java.protocol.handler.pkgs 指定实现类包名,实现类名必须为“Handler”,如果存在多包名指定,通过分隔符 “|”

 

Spring 资源接口

  • 资源接口
类型接口
输入流org.springframework.core.io.InputStreamSource
只读资源org.springframework.core.io.Resource
可写资源org.springframework.core.io.WritableResource
资源编码org.springframework.core.io.support.EncodedResource
上下文资源org.springframework.core.io.ContextResource

 

Spring 内建 Resource 实现

  • 内建实现
资源来源资源协议实现类
Bean定义org.springframework.beans.factory.support.BeanDefinitionResource
数组org.springframework.core.io.ByteArrayResource
类路径classpath:/org.springframework.core.io.ClassPathResource
文件系统file:/org.springframework.core.io.UrlResource
URLURL 支持的协议org.springframework.core.io.UrlResource
ServletContextorg.springframework.web.context.support.ServletContextResource

 

Spring Resource 接口扩展

  • 可写资源接口

org.springframework.core.io.WritableResource
  org.springframework.core.io.FileSystemResource
  org.springframework.core.io.FileUrlResource(@since 5.0.2)
  org.springframework.core.io.PathResource(@since 4.0 & @Deprecated)

  • 编码资源接口

org.springframework.core.io.support.EncodedResource

 

Spring 资源加载器

  • Resource 加载器

org.springframework.core.io.ResourceLoader
  org.springframework.core.io.DefaultResourceLoader
    org.springframework.core.io.FileSystemResourceLoader
    org.springframework.core.io.ClassRelativeResourceLoader
    org.springframework.context.support.AbstractApplicationContext

 

Spring 通配路径资源加载器

  • 通配路径 ResourceLoader

org.springframework.core.io.support.ResourcePatternResolver
  org.springframework.core.io.support.PathMatchingResourcePatternResolver

  • 路径匹配器

org.springframework.util.PathMatcher
  Ant模式匹配实现 - org.springframework.util.AntPathMatcher

 

Spring 通配路径资源扩展

  • 实现 org.springframework.util.PathMatcher
  • 重置PathMatcher

PathMatchingResourcePatternResolver#setPathMatcher

 

依赖注入 Spring Resource

  • 基于@Value 实现
如:
@Value("classpath:/...")
private Resource resource;

 

依赖注入ResourceLoader

  • 方法一:实现ResourceLoaderAware 回调

  • 方法二:@Autowired 注入 ResourceLoader

  • 方法三:注入ApplicationContext 作为 ResourceLoader

 

Spring 配置资源中有哪些常见类型?

  • XML 资源
  • Properties 资源
  • YAML 资源

 

请列举不同类型 Spring 配置资源?

  • XML 资源

普通Bean Definition XML 配置资源 -.xml
Spring Schema 资源 -
.xsd

  • Properties 资源

普通Properties 格式资源 -*.properties
Spring Handler 实现类映射文件 - META-INF/spring.handlers
Spring Schema 资源映射文件 - META-INF/spring.schemas

  • YAML 资源

普通YAML 资源配置 -*.yaml 或 *.yml

 

Java 标准资源管理扩展的步骤?

  • 简易实现
    实现URLStreamHandler 并放置在sun.net.www.protocol.${protocol}.Handler 包下

  • 自定义实现
    实现 URLStreamHandler
    添加 -Djava.protocol.handler.pkgs 启动参数,指向URLStreamHandler 实现类的包下

  • 高级实现
    实现URLStreamHandlerFactory并传递到URL之中

 

Spring 国际化使用场景

  • 普通国际化文案

  • Bean Validation 校验国际化文案

  • Web 站点页面渲染

  • Web MVC 错误消息提示

 

Spring 国际化接口

  • 核心接口
    org.springframework.context.MessageSource

  • 主要概念
    文案模板编码(code)
    文案模板参数(args)
    区域(Locale)

 

层次性 MessageSource

  • Spring层次性接口

org.springframework.beans.factory.HierarchicalBeanFactory
org.springframework.context.ApplicationContext
org.springframework.beans.factory.config.BeanDefinition

  • Spring 层次性国际化接口

org.springframework.context.HierarchicalMessageSource

 

Java国际化标准实现

  • 核心接口

抽象实现 - java.util.ResourceBundle

Properties 资源实现 - java.util.PropertyResourceBundle

举例实现 - java.util.ListResourceBundle

  • ResourceBundle 核心特性

Key - Value 设计

层次性设计

缓存设计

字符编码控制 - java.util.ResourceBundle.Control(@since 1.6)

Control SPI 扩展 - java.util.spi.ResourceBundleControlProvider(@since 1.8)

 

Java 文件格式化

  • 核心接口

java.text.MessageFormat

  • 基本用法

设置消息格式模式 - new MessageFormat(...)
格式化 - format(new Object[]{...})

  • 消息格式模式

格式元素:{ArgumentIndex(,FormatType,(FormatStyle))}
FormatType:消息格式类型,可选项,每种类型在number、date、time 和 choice 类型选其一
FormatStyle:消息格式风格,可选项,包括:short、medium、long、full、integer、currency、percent

  • 高级特性

重置消息格式模式

重置java.util.Locale

重置java.text.Format

 

MessageSource 开箱即用实现

  • 基于ResourceBundle + MessageFormat 组合 MessageSource 实现
    org.springframework.context.support.ResourceBundleMessageSource

  • 可重载Properties + MessageFormat 组合 MessageSource 实现
    org.springframework.context.support.ReloadableResourceBundleMessageSource

 

MessageSource 内建依赖

  • MessageSource 内建Bean 可能来源

预注册 Bean 名称为:"messageSource",类型为:MessageSource Bean

  • 默认内建实现 - DelegatingMessageSource

  层次性查找 MessageSource 对象

 

Spring Boot 为什么要新建MessageSource Bean?

  • AbstractApplicationContext 的实现决定了MessageSource 内建实现

  • Spring Boot 通过外部化配置简化 MessageSource Bean 构建

  • Spring Boot 基于 Bean Validation 校验非常普遍

 

Spring 国际化接口有哪些?

  • 核心接口 - MessageSource
  • 层次性接口 - org.springframework.context.HierarchicalMessageSource

 

Spring 有哪些MessageSource 内建实现?

  • org.springframework.context.support.ResourceBundleMessageSource

  • org.springframework.context.support.ReloadableResourceBundleMessageSource

  • org.springframework.context.support.StaticMessageSource

  • org.springframework.context.support.DelegatingMessageSource

 

如何实现配置自动更新MessageSource?

  • Java NIO 2:java.nio.file.WatchService

  • Java Concurrency:java.util.concurrent.ExecutorService

  • Spring:org.springframework.context.support.AbstractMessageSource

 

Spring 校验使用场景

  • Spring 常规校验(Validator)

  • Spring 数据绑定(DataBinder)

  • Spring Web 参数绑定(WebDataBinder)

  • Spring Web MVC / Spring WebFlux  处理方法参数校验

 

Validator 接口设计

  • 接口职责
    Spring 内部校验器接口,通过编程的方式校验目标对象

  • 核心方法
    supports(Class):校验目标类能否校验
    validate(Object,Errors):校验目标对象,并将校验失败的内容输出至Errors对象

  • 配套组件
    错误收集器:org.springframework.validation.Errors
    Validator工具类:org.springframework.validation.ValidationUtils

 

Errors 接口设计

  • 接口职责
    数据绑定和校验错误收集接口,与Java Bean 和其属性有强关联性

  • 核心方法
    reject 方法(重载):收集错误文案
    rejectValue 方法(重载):收集对象字段中的错误文案

  • 配套组件
    Java Bean 错误描述:org.springframework.validation.ObjectError
    Java Bean 属性错误描述:org.springframework.validation.FieldError

 

Errors 文案来源

Errors 文案生成步骤

  • 选择Errors实现(如:org.springframework.validation.BeanPropertyBindingResult

  • 调用reject 或 rejectValue 方法

  • 获取Errors 对象中ObjectError 或 FieldError

  • 将ObjectError 或 FieldError 中的 code 和 args ,关联 MessageSource 实现(如:ResourceBundleMessageSource

 

自定义Validator

实现org.springframework.validation.Validator 接口

  • 实现 supports 方法

  • 实现 validate 方法
    通过Errors 对象收集错误
      ObjectError:对象(Bean)错误
      FieldError:对象(Bean)属性(Property)错误

    通过ObjectError 和 FieldError 关联 MessageSource 实现获取最终文案

 

Validator 的救赎

Bean Validation 和 Validator 适配

  • 核心组件 - org.springframework.validation.beanvalidation.LocalValidatorFactoryBean

  • 依赖Bean Validation - JSR-303 or JSR-349 provider

  • Bean 方法参数校验 - org.springframework.validation.beanvalidation.MethodValidationPostProcessor

 

Spring 校验接口是哪个?

org.springframework.validation.Validator

 

Spring 有哪些校验核心组件?

  • 校验器:org.springframework.validation.Validator

  • 错误收集器:org.springframework.validation.Errors

  • Java Bean 错误描述:org.springframework.validation.ObjectError

  • Java Bean 属性错误描述:org.springframework.validation.FieldError

  • Bean Validation 适配:org.springframework.validation.beanvalidation.LocalValidatorFactoryBean

 

Spring 数据绑定使用场景

  • Spring BeanDefinition 到 Bean 实例创建

  • Spring 数据绑定(DataBinder)

  • Spring Web 参数绑定(WebDataBinder)

 

Spring 数据绑定组件

  • 标准组件

org.springframework.validation.DataBinder

  • Web 组件

org.springframework.web.bind.WebDataBinder
org.springframework.web.bind.ServletRequestDataBinder
org.springframework.web.bind.support.WebRequestDataBinder
org.springframework.web.bind.support.WebExchangeDataBinder(since 5.0)

 

Spring 数据绑定组件

  • DataBinder 核心属性
属性说明
target关联目标 Bean
objectName目标Bean名称
bindingResult属性绑定结果
typeConverter类型转换器
conversionService类型转换服务
messageCodesResolver校验错误文案Code处理器
validators关联的Bean Validator 实例集合
  • DataBinder 绑定方法

bind(PropertyValues):将PropertyValues Key - Value 内容映射到关联Bean(target)中的属性上
假设PropertyValues 中包含“name = vincent” 的键值对,同时Bean对象User 中存在name 属性,当bind 方法执行时,User对象中的 name 属性值将被绑定为“vincent”

 

Spring 数据绑定元数据

  • DataBinder 元数据 - PropertyValues
特征说明
数据来源BeanDefinition,主要来源XML资源配置 BeanDefinition
数据结构由一个或多个PropertyValue 组成
成员结构PropertyValue 包含属性名称,以及属性值(包括原始值、类型转换后的值)
常见实现MutablePropertyValues
Web扩展实现ServletConfigPropertyValues、ServletRequestParameterPropertyValues
相关声明周期InstantiationAwareBeanPostProcessor#postProcessProperties

 

Spring 数据绑定控制参数

  • DataBinder 绑定控制参数
参数名称说明
ignoreUnknownFields是否忽略未知字段,默认值:true
ignoreInvalidFields是否忽略非法字段,默认值:false
autoGrowNestedPaths是否自动增加嵌套路径,默认值:true
allowedFields绑定字段白名单
disallowedFields绑定字段黑名单
requiredFields必须绑定字段

 

BeanWrapper 的使用场景

  • Spring 底层JavaBeans 基础设施的中心化接口

  • 通常不会直接使用,间接用于BeanFactory 和 DataBinder

  • 提供标准JavaBeans 分析和操作,能够单独或批量存储Java Bean 的属性(properties)

  • 支持嵌套属性路径(nested path)

  • 实现类 org.springframework.beans.BeanWrapperImpl

 

Spring底层Java Beans 替换实现

  • JavaBeans 核心实现 - java.beans.BeanInfo
    属性(Property):java.beans.PropertyEditor
    方法(Method)
    事件(Event)
    表达式(Expression)

  • Spring 替换实现 - org.springframework.beans.BeanWrapper
    属性(Property):java.beans.PropertyEditor
    嵌套属性路径(nested path)

 

标准 JavaBeans 是如何操作属性的?

API说明
java.beans.IntrospectorJavaBeans 内省 API
java.beans.BeanInfoJavaBeans 元信息API
java.beans.BeanDescriptorJavaBeans 信息描述符
java.beans.PropertyDescriptorJavaBeans 属性描述符
java.beans.MethodDescriptorJavaBeans 方法描述符
java.beans.EventSetDescriptorJavaBeans 事件集合描述符

 

DataBinder 数据校验

  • DataBinder 与 BeanWrapper

bind 方法生成 BeanPropertyBindingResult

BeanPropertyBindingResult 关联 BeanWrapper

 

Spring 数据绑定API 是什么?

org.springframwork.validation.DataBinder

 

BeanWrapper 与 JavaBeans 之间关系是?

Spring 底层 JavaBeans 基础设施的中心化接口

 

Spring 类型转换的实现

  • 基于 JavaBeans 接口的类型转换实现
    基于 java.beans.PropertyEditor 接口扩展

  • Spring 3.0+ 通用类型转换实现

 

使用场景

场景基于JavaBeans 接口的类型转换实现Spring 3.0+ 通用类型转换实现
数据绑定YESYES
BeanWrapperYESYES
Bean 属性类型转换YESYES
外部化属性类型转换NOYES

 

基于 JavaBeans 接口的类型转换

  • 核心职责
    将 String 类型的内容转化为目标类型的对象

  • 扩展原理
    Spring 框架将文本内容传递到PropertyEditor 实现的setAsText(String)方法

    PropertyEditor#setAsText(String)方法实现将String类型转换为目标类型的对象

    将目标类型的对象传入PropertyEditor#setValue(Object) 方法

    PropertyEditor#setValue(Object)方法实现需要临时存储传入对象

    Spring 框架将通过PropertyEditor#getValue() 获取类型转换后的对象

 

Spring 内建 PropertyEditor 扩展

  • 内建扩展(org.springframework.beans.propertyeditors 包下)
转换场景实现类
String -> Byte 数组org.springframework.beans.propertyeditors.ByteArrayPropertyEditor
String -> Charorg.springframework.beans.propertyeditors.CharacterEditor
String -> Char 数组org.springframework.beans.propertyeditors.CharArrayPropertyEditor
String ->Charsetorg.springframework.beans.propertyeditors.CharsetEditor
String -> Classorg.springframework.beans.propertyeditors.ClassEditor
String -> Currencyorg.springframework.beans.propertyeditors.CurrencyEditor
......

 

自定义 PropertyEditor 扩展

  • 扩展模式
    扩展java.beans.PropertyEditorSupport 类

  • 实现 org.springframework.beans.PropertyEditorRegistrar
      实现 registerCustomEditors(org.springframework.beans.PropertyEditorRegistry) 方法
      将PropertyEditorRegistrar 实现注册为Spring Bean

  • 向 org.springframework.beans.PropertyEditorRegistry 注册自定义PropertyEditor实现
      通用类型实现 registerCustomEditor(Class<?>,PropertyEditor)
      Java Bean 属性类型实现:registerCustomEditor(Class<?>,String,PropertyEditor)

 

Spring PropertyEditor 的设计缺陷

  • 违反职责单一原则
    java.beans.PropertyEditor 接口职责太多,除了类型转换,还包括Java Beans 事件 和Java GUI 交互

  • java.beans.PropertyEditor 实现类型局限
    来源类型只能为java.lang.String 类型

  • java.beans.PropertyEditor 实现缺少类型安全
    除了实现类命名可以表达语义,实现类无法感知目标转换类型

 

Spring 3 通用类型转换接口

  • 类型转换接口- org.springframework.core.convert.converter.Converter<S,T>
    泛型参数S:来源类型,参数T:目标类型
    核心方法:T convert(S)

  • 通用类型转换接口 - org.springframework.core.convert.converter.GenericConverter
    核心方法:convert(Object,TypeDescriptor,TypeDescriptor)
    配对类型:org.springframework.core.convert.converter.GenericConverter.ConvertiblePair
    类型描述:org.springframework.core.convert.TypeDescriptor

 

Spring 内建类型转换器

  • 内建扩展
转换场景实现类所在包名(package)
日期/时间相关org.springframework.format.datetime
Java 8 日期 / 时间相关org.springframework.format.datetime.standard
通用实现org.springframework.core.convert.support

 

Converter 接口的局限性

  • 局限一:缺少Source Type 和 Target Type 前置判断
    应对:增加org.springframework.core.converter.ConditionalConverter 实现

  • 局限二:仅能转换单一的Source Type 和 Target Type
    应对:使用org.springframework.core.convert.converter.GenericConverter 代替

 

GenericConverter 接口

  • org.springframework.core.convert.converter.GenericConverter
核心要素说明
使用场景用于“复合”类型转换场景,比如Collection、Map、数组等
转换范围Set<ConvertiblePair>  getConvertibleTypes()
配对类型org.springframework.core.convert.converter.GenericConverter.ConvertiblePair
转换方法convert(Object source,TypeDescriptor sourceType,TypeDescriptor targetType)
类型描述org.springframework.core.convert.TypeDescriptor

 

优化GenericConverter 接口

  • GenericConverter 局限性
    缺少 Source Type 和 Target Type 前置判断
    单一类型转换实现复杂

  • GenericConverter 优化接口 - ConditionalGenericConverter
    复合类型转换:org.springframework.core.convert.converter.GenericConverter
    类型条件判断:org.springframework.core.convert.converter.ConditionalConverter

 

扩展Spring 类型转换器

  • 实现转换器接口
    org.springframework.core.convert.converter.Converter
    org.springframework.core.convert.converter.ConverterFactory
    org.springframework.core.convert.converter.GenericConverter

  • 注册转换器实现
    通过ConversionServiceFactoryBean Spring Bean
    通过org.springframework.core.convert.ConversionService API

 

统一类型转换服务

  • org.springframework.core.convert.ConversionService
实现类型说明
GenericConversionService通用ConversionService模板实现,不内置转化器实现
DefaultConversionService基础ConversionSerivce实现,内置常用转化器实现
FormattingConversionService通用Formatter + GenericConversionService 实现,不内置转化器和Formatter实现
DefaultFormattingConversionServiceDefaultConversionService + 格式化实现(如:JSR-354 Money & Currency,JSR-310 Date-Time)

 

ConversionService 作为依赖

  • 类型转换器底层接口 - org.springframework.beans.TypeConverter

  • 起始版本:Spring 2.0
  • 核心方法 - convertIfNecessary重载方法
  • 抽象实现 - org.springframework.beans.TypeConverterSupport
  • 简单实现 - org.springframework.beans.SimpleTypeConverter
  • 类型转换器底层抽象实现

  • 实现接口 - org.springframework.beans.TypeConverter
  • 扩展实现 - org.springframework.beans.PropertyEditorRegistrySupport
  • 委派实现 - org.springframework.beans.TypeConverterDelegate
  • 类型转换器底层委派实现 - org.springframework.beans.TypeConverterDelegate

  • 构造来源 - org.springframework.beans.AbstractNestablePropertyAccessor 实现

  org.springframework.beans.BeanWrapperImpl

  • 依赖 - java.beans.PropertyEditor 实现

  默认内建实现 - PropertyEditorRegistrySupport#registerDefaultEditors

  • 可选依赖 - org.springframework.core.convert.ConversionService 实现

 

Spring 类型转换实现有哪些?

  • 基于JavaBeans PropertyEditor 接口实现
  • Spring 3.0+ 通用类型转换实现

 

Spring 类型转换器接口有哪些?

  • 类型转换接口 - org.springframework.core.convert.converter.Converter

  • 通用类型转换接口 - org.springframework.core.convert.converter.GenericConverter

  • 类型条件接口 - org.springframework.core.convert.converter.ConditionalConverter

  • 综合类型转换接口 - org.springframwork.core.convert.converter.ConditionalGenericConverter

 

Java 泛型基础

  • 泛型类型

泛型类型是在类型上参数化的泛型类或接口

  •  泛型使用场景
  •  编译时强类型检查
  • 避免类型强转
  • 实现通用算法
  • 泛型类型擦写

泛型被引入到 Java 语言中,以便在编译时提供更严格的类型检查并支持泛型编程。类型擦除确保不会为参数化类型创建新类;因此,泛型不会产生运行时开销。为了实现泛型,编译器将类型擦除应用于:

  •  将泛型类型中的所有类型参数替换为其边界,如果类型参数是无边界的,则将其替换为“Object”。因此,生成的字节码只包含普通类、接口和方法
  • 必要时插入类型转换以保持类型安全
  • 生成桥方法以保留扩展泛型类型中的多态性

 

Java 5 类型接口

  •  Java 5 类型接口 - java.lang.reflect.Type
派生类或接口说明
java.lang.ClassJava 类 API,如java.lang.String
java.lang.reflect.GenericArrayType泛型数组类型
java.lang.reflect.ParameterizedType泛型参数类型
java.lang.reflect.TypeVariable泛型类型变量,如Collection<E>中的E
java.lang.reflect.WildcardType泛型通配类型
  •  Java 泛型反射 API
类型API
泛型信息(Generics Info)java.lang.Class#getGenericInfo()
泛型参数(Parameters)java.lang.reflect.ParameterizedType
泛型父类(Super Classes)java.lang.Class#getGenericSuperclass()
泛型接口(Interfaces)java.lang.Class#getGenericInterfaces()
泛型声明(Generics Delaration)java.lang.reflect.GenericDeclaration

 

Spring 泛型类型辅助类

  •  核心 API - org.springframework.core.GenericTypeResolver

• 版本支持:[2.5.2 , )
• 处理类型相关(Type)相关方法
      • resolveReturnType
      • resolveType
• 处理泛型参数类型(ParameterizedType)相关方法
      • resolveReturnTypeArgument
      • resolveTypeArgument
      • resolveTypeArguments
• 处理泛型类型变量(TypeVariable)相关方法
      • getTypeVariableMap

 

Spring 泛型集合类型辅助类

  • 核心 API - org.springframework.core.GenericCollectionTypeResolver
  • 版本支持:[2.0 , 4.3]
  • 替换实现:org.springframework.core.ResolvableType
  • 处理 Collection 相关

      • getCollection*Type

  • 处理 Map 相关

      • getMapKey*Type
      • getMapValue*Type

 

Spring 方法参数封装

  • 核心 API - org.springframework.core.MethodParameter
  • 起始版本:[2.0 , )
  • 元信息

      • 关联的方法 - Method
      • 关联的构造器 - Constructor
      • 构造器或方法参数索引 - parameterIndex
      • 构造器或方法参数类型 - parameterType
      • 构造器或方法参数泛型类型 - genericParameterType
      • 构造器或方法参数参数名称 - parameterName
      • 所在的类 - containingClass

 

Spring 4.0 泛型优化实现 - ResolvableType

  • 核心 API - org.springframework.core.ResolvableType

• 起始版本:[4.0 , )
• 扮演角色:GenericTypeResolver 和 GenericCollectionTypeResolver 替代者
• 工厂方法:for* 方法
• 转换方法:as* 方法
• 处理方法:resolve* 方法

 

ResolvableType 的局限性

• 局限一:ResolvableType 无法处理泛型擦写
• 局限二:ResolvableType 无法处理非具体化的 ParameterizedType

 

 Java 泛型擦写发生在编译时还是运行时?

运行时

 

请介绍 Java 5 Type 类型的派生类或接口?

  •  java.lang.Class
  •  java.lang.reflect.GenericArrayType
  •  java.lang.reflect.ParameterizedType
  •  java.lang.reflect.TypeVariable
  •  java.lang.reflect.WildcardType

 

请说明 ResolvableType 的设计优势?

  • 简化 Java 5 Type API 开发,屏蔽复杂 API 的运用,如 ParameterizedType
  • 不变性设计(Immutability)
  • Fluent API 设计(Builder 模式),链式(流式)编程

 

Java事件/监听器编程模型

  • 设计模式 - 观察者模式扩展
  • 可观者对象(消息发送者)- java.util.Observable
  • 观察者 - java.util.Observer
  • 标准化接口
  • 事件对象 - java.util.EventObject
  • 事件监听器 - java.util.EventListener

 

面向接口的事件/监听器设计模式

  • 事件/监听器场景举例
Java技术规范事件接口监听器接口
JavaBeansjava.beans.PropertyChangeEventjava.beans.PropertyChangeListener
Java AWTjava.awt.event.MouseEventjava.awt.event.MouseListener
Java Swingjavax.swing.event.MenuEventjavax.swing.event.MenuListener
Java Preferencejava.util.prefs.PreferenceChangeEventjava.util.prefs.PreferenceChangeListener

 

面向注解的事件/监听器设计模式

  • 事件/监听器注解场景举例
Java技术规范事件注解监听器注解
Servlet 3.0+ @javax.servlet.annotation.WebListener
JPA 1.0+@javax.persistence.PostPersist 
Java Common@PostConstruct 
EJB 3.0+@javax.ejb.PrePassivate 
JSF 2.0+@javax.faces.event.ListenerFor 

 

Spring 标准事件 - ApplicationEvent

  • Java 标准事件 java.util.EventObject 扩展

扩展特性:事件发生事件戳

  • Spring 应用上下文 ApplicationEvent扩展 - ApplicationContextEvent
  1. Spring 应用上下文(ApplicationContext)作为事件源
  2. 具体实现
  • org.springframework.context.event.ContextClosedEvent
  • org.springframework.context.event.ContextRefreshedEvent
  • org.springframework.context.event.ContextStartedEvent
  • org.springframework.context.event.ContextStoppedEvent

 

基于接口的Spring事件监听器

  • Java 标准事件监听器 java.util.EventListener 扩展
  • 扩展接口 - org.springframework.context.ApplicationListener
  • 设计特点: 单一类型事件处理
  • 处理方法:onApplicationEvent(ApplicationEvent)
  • 事件类型:org.springframework.context.ApplicationEvent

 

基于注解的 Spring 事件监听器

  • Spring 注解 - @org.springframework.context.event.EventListener
特性说明
设计特点支持多ApplicationEvent类型,无需接口约束
注解目标方法
是否支持异步执行支持
是否支持泛型类型事件支持
是否支持顺序控制支持,配合@order 注解控制

 

注册Spring ApplicationListener

方法一:ApplicationListener 作为Spring Bean 注册

方法二:通过ConfigurableApplicationContext API注册

 

Spring 事件发布器

方法一:通过 ApplicationEventPublisher 发布 Spring 事件

  • 获取ApplicationEventPublisher
  •       依赖注入

方法二:通过ApplicationEventMulticaster 发布 Spring 事件

  • 获取ApplicationEventMulticaster
  •       依赖注入
  •       依赖查找

 

Spring 层次性上下文事件传播

  • 发生说明

当Spring 应用出现多层次Spring 应用上下文(ApplicationContext)时,如Spring WebMVC、Spring Boot 或Spring Cloud场景下,由子ApplicationContext 发起Spring事件可能会传递到其Parent ApplicationContext(直到Root)的过程

  • 如何避免

定位Spring事件源(ApplicationContext)进行过滤处理

 

Spring 内建事件

  • ApplicationContextEvent 派生事件
  • ContextRefreshedEvent:Spring 应用上下文就绪事件
  • ContextStartedEvent:Spring 应用上下文启动事件
  • ContextStoppedEvent:Spring 应用上下文停止事件
  • ContextClosedEvent:Spring 应用上下文关闭事件

 

Spring 4.2 Payload 事件

  • Spring Payload 事件 - org.springframework.context.PayloadApplicationEvent
  • 使用场景:简化 Spring 事件发送,关注事件源主体
  • 发送方法

   ApplicationEventPublisher#publishEvent(java.lang.Object)

 

自定义 Spring 事件

  • 扩展 org.springframework.context.ApplicationEvent
  • 实现 org.springframework.context.ApplicationListener
  • 注册 org.springframework.context.ApplicationListener

 

依赖注入ApplicationEventPublisher

  • 通过ApplicationEventPublisherAware 回调接口
  • 通过@Autowired ApplicationEventPublisher

 

依赖查找ApplicationEventMulticaster

  • 查找条件
  • Bean 名称:“applicationEventMulticaster”
  • Bean 类型:org.springframework.context.event.ApplicationEventMulticaster

 

ApplicationEventPublisher 底层实现

  • 底层实现
  • 接口:org.springframework.context.event.ApplicationEventMulticaster
  • 抽象类:org.springframework.context.event.AbstractApplicationEventMulticaster
  • 实现类:org.springframework.context.event.SimpleApplicationEventMulticaster

 

同步和异步Spring 事件广播

  • 基于实现类 - org.springframework.context.event.SimpleApplicationEventMulticaster
  • 模式切换:setTaskExecutor(java.util.concurrent.Executor) 方法

默认模式:同步

异步模式:如 java.util.concurrent.ThreadPoolExecutor

  • 设计缺陷:非基于接口契约编程
  • 基于注解 - @org.springframework.context.event.EventListener
  • 模式切换

默认模式:同步

异步模式:标注 @org.springframework.scheduling.annotation.Async

  • 实现限制:无法直接实现同步/异步动态切换

 

Spring4.1 事件异常处理

  • Spring 3.0 错误处理接口 - org.springframework.util.ErrorHandler

使用场景

  • Spring 事件(Events)

SimpleApplicationEventMulticaster Spring 4.1 开始支持

  • Spring 本地调度(Scheduling)

org.springframework.scheduling.concurrent.ConcurrentTaskScheduler

org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler

 

Spring  事件/监听器实现原理

  • 核心类 - org.springframework.context.SimpleApplicationEventMulticaster
  • 设计模式:观察者模式扩展

被观察者 - org.springframework.context.ApplicationListener

      API 添加

      依赖查找

通知对象 - org.springframework.context.ApplicationEvent

  • 执行模式:同步/异步
  • 异常处理:org.springframework.core.ErrorHandler
  • 泛型处理:org.springframework.core.ResolvableType

 

Spring Boot 事件

事件类型发生时机
ApplicationStartingEvent当Spring Boot 应用已启动时
ApplicationStartedEvent当Spring Boot 应用启动了
ApplicationEnvironmentPreparedEvent当Spring Boot Environment 实例已准备时
ApplicationPreparedEvent当Spring Boot 应用预备时
ApplicationReadyEvent当Spring Boot 应用完全可用时
ApplicationFailedEvent当Spring Boot 应用启动失败时

 

Spring Cloud 事件

事件类型发生时机
EnvironmentChangeEvent当 Environment 实例配置属性发生变化时
HeartbeatEvent当 DiscoveryClient 客户端发送心跳时
InstancePreRegisteredEvent当服务实例注册前
InstanceRegisteredEvent当服务实例注册后
RefreshEvent当 RefreshEndpoint 被调用时
RefreshScopeRefreshedEvent当Refresh Scope Bean 刷新后

 

Spring 事件核心接口/组件?

  • Spring 事件 - org.springframework.context.ApplicationEvent
  • Spring 事件监听器 - org.springframework.context.ApplicationListener
  • Spring 事件发布器 - org.springframework.context.ApplicationEventPublisher
  • Spring 事件广播器 - org.springframework.context.event.ApplicationEventMulticaster

 

Spring 同步和异步事件处理的使用场景?

  • Spring 同步事件

绝大多数Spring使用场景,如ContextRefreshedEvent

  • Spring 异步事件

主要@EventListener 与 @Asyc配合,实现异步处理,不阻塞主线程,比如长时间的数据计算任务等,不要轻易调整SimpleApplicationEventMulticaster中关联的taskExecutor 对象,除非使用者非常了解Spring 事件机制,否则容易出现异常行为

 

Spring 注解驱动编程发展历程

注解驱动启蒙时代:Spring Framework 1.x

注解驱动过渡时代:Spring Framework 2.x

注解驱动黄金时代:Spring Framework 3.x

注解驱动完善时代:Spring Framework 4.x

注解驱动当下时代:Spring Framework 5.x

 

Spring 核心注解场景分类

  • Spring 模式注解
Spring 注解场景说明起始版本
@Repository数据仓储模式注解2.0
@Component通用组件模式注解2.5
@Service服务模式注解2.5
@ControllerWeb 控制器模式注解2.5
@Configuration配置类模式注解3.0
  • 装配注解
Spring 注解场景说明起始版本
@ImportResource替换XML元素<import>2.5
@Import导入Configuration 类2.5
@ComponentScan扫描指定package 下标注Spring模式注解的类3.1
  • 依赖注入注解
Spring 注解场景说明起始版本
@AutowiredBean 依赖注入,支持多种依赖查找方式2.5
@Qualifier细粒度的@Autowired 依赖查找2.5

 

Spring 注解编程模型(https://github.com/spring-projects/spring-framework/wiki/Spring-Annotation-Programming-Model

  • 元注解(Meta-Annotations)
  • Spring 模式注解(Stereotype Annotations)
  • Spring 组合注解(Composed Annotations)
  • Spring 注解属性别名和覆盖(Attribute Aliases and Overrides)

 

Spring 元注解(Meta-Annotations)

  • 官方Wiki 原文

meta-annotation is an annotation that is declared on another annotation. An annotation is therefore meta-annotated if it is annotated with another annotation. For example, any annotation that is declared to be documented is meta-annotated with @Documented from the java.lang.annotation package.

  • 举例说明

java.lang.annotation.Documented

java.lang.annotation.Inherited

java.lang.annotation.Repeatable

 

Spring 模式注解(Stereotype Annotations)

  • 官方Wiki原文

stereotype annotation is an annotation that is used to declare the role that a component plays within the application. For example, the @Repository annotation in the Spring Framework is a marker for any class that fulfills the role or stereotype of a repository (also known as Data Access Object or DAO).

@Component is a generic stereotype for any Spring-managed component. Any component annotated with @Component is a candidate for component scanning. Similarly, any component annotated with an annotation that is itself meta-annotated with @Component is also a candidate for component scanning. For example, @Service is meta-annotated with @Component.

Core Spring provides several stereotype annotations out of the box, including but not limited to: @Component@Service@Repository@Controller@RestController, and @Configuration@Repository@Service, etc. are specializations of @Component.

  • 理解@Component “派生性”

元标注@Component 的注解在XML 元素<context:component-scan>或注解@ComponentScan 扫描中“派生”了@Component 的特性,并且从Spring Framework4.0 开始支持多层次“派生性”

  • 举例说明
  • @Repository
  • @Service
  • @Controller
  • @Configuration
  • @SpringBootConfiguration(Spring Boot)
  • @Component “派生性”原理
  • 核心组件 - org.springframework.context.annotation.ClassPathBeanDefinitionScanner

org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider

  • 资源处理 - org.springframework.core.io.support.ResourcePatternResolver
  • 资源 -  类元信息

org.springframework.core.type.classreading.MetadataReaderFactory

  • 类元信息 - org.springframework.core.type.ClassMetadata

ASM 实现 - org.springframework.core.type.classreading.ClassMetadataReadingVisitor

反射实现 - org.springframework.core.type.StandardAnnotationMetadata

  • 注解元信息 - org.springframework.core.type.AnnotationMetadata

ASM 实现 - org.springframework.core.type.classreading.AnnotationMetadataReadingVisitor

反射实现 - org.springframework.core.type.StandardAnnotationMetadata

 

Spring 组合注解(Composed Annotations)

  • 官方Wiki 原文

composed annotation is an annotation that is meta-annotated with one or more annotations with the intent of combining the behavior associated with those meta-annotations into a single custom annotation. For example, an annotation named @TransactionalService that is meta-annotated with Spring's @Transactional and @Service annotations is a composed annotation that combines the semantics of @Transactional and @Service@TransactionalService is technically also a custom stereotype annotation.

  • 基本定义

Spring 组合注解(Composed Annotations)中的元注允许是Spring模式注解(Stereotype Annotation)与其他Spring 功能性注解的任意组合

 

Spring 注解属性别名(Attribute Aliases)

  • 官方Wiki 原文

An attribute alias is an alias from one annotation attribute to another annotation attribute. Attributes within a set of aliases can be used interchangeably and are treated as equivalent. Attribute aliases can be categorized as follows.

  1. Explicit Aliases: if two attributes in one annotation are declared as aliases for each other via @AliasFor, they are explicit aliases.
  2. Implicit Aliases: if two or more attributes in one annotation are declared as explicit overrides for the same attribute in a meta-annotation via @AliasFor, they are implicit aliases.
  3. Transitive Implicit Aliases: given two or more attributes in one annotation that are declared as explicit overrides for attributes in meta-annotations via @AliasFor, if the attributes effectively override the same attribute in a meta-annotation following the law of transitivity, they are transitive implicit aliases.

 

Spring 注解属性覆盖(Attribute Overrides)

  • 官方Wiki 原文

An attribute override is an annotation attribute that overrides (or shadows) an annotation attribute in a meta-annotation. Attribute overrides can be categorized as follows.

  1. Implicit Overrides: given attribute A in annotation @One and attribute A in annotation @Two, if @One is meta-annotated with @Two, then attribute A in annotation @One is an implicit override for attribute A in annotation @Two based solely on a naming convention (i.e., both attributes are named A).
  2. Explicit Overrides: if attribute A is declared as an alias for attribute B in a meta-annotation via @AliasFor, then A is an explicit override for B.
  3. Transitive Explicit Overrides: if attribute A in annotation @One is an explicit override for attribute B in annotation @Two and B is an explicit override for attribute C in annotation @Three, then A is a transitive explicit override for C following the law of transitivity.

 

Spring @Enable 模块驱动

  • @Enable 模块驱动

@Enable 模块驱动是以@Enable 为前缀的注解驱动编程模型,所谓“模块”是指具备相同领域的功能组件集合,组合所形成一个独立的单元。比如Web MVC模块、AspectJ代理模块、Caching(缓存)模块、JMX(Java管理扩展)模块、Async(异步处理)模块等

  • 举例说明
  • @EnableWebMvc
  • @EnableTransactionManagement
  • @EnableCaching
  • @EnableMBeanExport
  • @EnableAsync
  • @Enable 模块驱动编程模式
  • 驱动注解:@EnableXXX
  • 导入注解:@Import 具体实现
  • 具体实现
  1. 基于Configuration Class
  2. 基于ImportSelector 接口实现
  3. 基于ImportBeanDefinitionRegistrar 接口实现

 

Spring 条件注解

  • 基于配置条件注解 - @org.springframework.context.annotation.Profile

关联对象 -  org.springframework.core.env.Environment 中的 Profiles

实现变化:从Spring 4.0 开始,@Profile 基于@Conditional 实现

  • 基于编程条件注解 - org.springframework.context.annotation.Conditional

关联对象 - org.springframework.context.annotation.Condition 具体实现

  • @Conditional 实现原理
  • 上下文对象 - org.springframework.context.annotation.ConditionContext
  • 条件判断 - org.springframework.context.annotation.ConditionEvaluator
  • 配置阶段 - org.springframework.context.annotation.ConfigurationCondition.ConfigurationPhase
  • 判断入口 - org.springframework.context.annotation.ConfigurationClassPostProcessor

      org.springframework.context.annotation.ConfigurationClassParser

 

Spring Boot 注解

注解场景说明起始版本
@SpringBootConfigurationSpring Boot 配置类1.4.0
@SpringBootApplicationSpring Boot 应用引导注解1.2.0
@EnableAutoConfigurationSpring Boot 激活自动转配1.0.0

 

Spring Cloud 注解

注解场景说明起始版本
@SpringCloudApplicationSpring Cloud 应用引导注解1.0.0
@EnableDiscoveryClientSpring Cloud 激活服务发现客户端注解1.0.0
@EnableCircuitBreakerSpring Cloud 激活熔断注解1.0.0

 

Spring 模式注解有哪些?

  • @org.springframework.stereotype.Component
  • @org.springframework.stereotype.Repository
  • @org.springframework.stereotype.Service
  • @org.springframework.stereotype.Controller
  • @org.springframework.context.annotation.Configuration

 

@EventListener的工作原理?

详见源码:org.springframework.context.event.EventListenerMethodProcessor

 

理解 Spring Environment 抽象

  • 统一的Spring 配置属性管理

Spring Framework 3.1 开始引入 Environment 抽象,它统一Spring 配置属性的存储,包括占位符处理和类型转换,不仅完整地替换PropertyPlaceholderConfigurer,而且还支持更丰富的配置属性源(PropertySource)

  • 条件化 Spring Bean 装配管理

通过Environment Profiles 信息,帮助Spring 容器提供条件化地装配Bean

 

Spring Environment 接口使用场景

  • 用于属性占位符处理
  • 用于转换Spring配置属性类型
  • 用于存储Spring 配置属性源
  • 用于Profiles 状态的维护

 

Environment 占位符处理

  • Spring 3.1 前占位符处理

组件:org.springframework.beans.factory.config.PropertyPlaceholderConfigurer

接口:org.springframework.util.StringValueResolver

  • Spring 3.1+ 占位符处理

组件:org.springframework.context.support.PropertySourcesPlaceholderConfigurer

接口:org.springframework.beans.factory.config.EmbeddedValueResolver

 

理解条件配置Spring Profiles

  • Spring 3.1 条件配置
  • API:org.springframework.core.env.ConfigurableEnvironment

修改:addActiveProfile(String)、setActiveProfiles(String...)和setDefaultProfiles(String...)

获取:getActiveProfiles() 和 getDefaultProfiles()

匹配:acceptsProfiles(String...) 和 acceptsProfiles(Profiles)

  • 注解:@org.springframework.context.annotation.Profile
  • 基于Spring 4 org.springframework.context.annotation.Condition 接口实现

org.springframework.context.annotation.ProfileCondition

 

依赖注入 Environment

  • 直接依赖注入

通过EnvironmentAware 接口回调

通过@Autowired 注入 Environment

  • 间接依赖注入

通过 ApplicationContextAware 接口回调

通过@Autowired 注入ApplicationContext

 

依赖查找Environment

  • 直接依赖查找

通过org.springframework.context.ConfigurableApplicationContext#ENVIRONMENT_BEAN_NAME

  • 间接依赖查找

通过 org.springframework.context.ConfigurableApplicationContext#getEnvironment

 

依赖注入@Value

  • 通过注入@Value

实现 - org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor

 

Spring 类型转换在 Environment 中的运用

  • Environment  底层实现
  • 底层实现 - org.springframework.core.env.PropertySourcesPropertyResolver

核心方法 - convertValueIfNecessary(Object,Class)

  • 底层服务 - org.springframework.core.convert.ConversionService

默认实现 - org.springframework.core.convert.support.DefaultConversionService

 

Spring 类型转换在@Value 中的运用

  • @Value 底层实现
  • 底层实现 - org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor

org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency

  • 底层服务 - org.springframework.beans.TypeConverter

默认实现 - org.springframework.beans.TypeConverterDelegate

java.beans.PropertyEditor

org.springframework.core.convert.ConversionService

 

Spring 配置属性源 PropertySource

  • API

单配置属性源 - org.springframework.core.env.PropertySource 

多配置属性源 - org.springframework.core.env.PropertySources 

  • 注解

单配置属性源 - @org.springframework.context.annotation.PropertySource 

多配置属性源 - @org.springframework.context.annotation.PropertySources

  • 关联

存储对象 - org.springframework.core.env.MutablePropertySources

关联方法 - org.springframework.core.env.ConfigurableEnvironment#getPropertySources()

 

Spring 内建的配置属性源

  • 内建 PropertySource
PropertySource 类型说明
org.springframework.core.env.CommandLinePropertySource命令行配置属性源
org.springframework.jndi.JndiPropertySourceJNDI 配置属性源
org.springframework.core.env.PropertiesPropertySourceProperties 配置属性源
org.springframework.web.context.support.ServletConfigPropertySourceSerlvet 配置属性源
org.springframework.web.context.support.ServletContextPropertySourceServletContext 配置属性源
org.springframework.core.env.SystemEnvironmentPropertySource环境变量配置属性源
......

 

基于注解扩展 Spring 配置属性源

  • @org.springframework.context.annoatation.PropertySource 实现原理
  • 入口 - org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass

org.springframework.context.annotation.ConfigurationClassParser#processPropertySource

  • 4.3 新增语义

配置属性字符编码 - encoding

org.springframework.core.io.support.PropertySourceFactory 

  • 适配对象 - org.springframework.core.env.CompositePropertySource

 

基于API 扩展Spring 配置属性源

Spring 应用上下文启动前装配 PropertySource

Spring 应用上下文启动后装配 PropertySource

 

简单介绍 Spring Environment 接口?

  • 核心接口 - org.springframework.core.env.Environment
  • 父接口 - org.springframework.core.env.PropertyResolver
  • 可配置接口 - org.springframework.core.env.ConfigurableEnvironment
  • 职责

管理Spring 配置属性源

管理Profiles

 

Spring 应用上下文启动准备阶段

  • 启动时间 - startupDate
  • 状态标识 - closed(false)、active(true) 
  • 初始化 PropertySources - initPropertySources()
  • 检验Environment 中必须属性
  • 初始化事件监听器集合
  • 初始化早期Spring 事件集合

 

BeanFactory 创建阶段

  • AbstractApplicationContext#obtainFreshBeanFactory()方法
  • 刷新Spring 应用上下文底层BeanFactory - refreshBeanFactory()
  1. 销毁或关闭BeanFactory,如果已存在的话
  2. 创建BeanFactory - createBeanFactory()
  3. 设置BeanFactory Id
  4. 设置“是否允许BeanDefinition重复定义” - customizeBeanFactory(DefaultListableBeanFactory)
  5. 设置“是否运行循环引用(依赖)” - customizeBeanFactory(DefaultListableBeanFactory)
  6. 加载BeanDefinition - loadBeanDefinitions(DefaultListableBeanFactory)方法
  7. 关联新建 BeanFactory 到 Spring 应用上下文
  • 返回Spring 应用上下文底层BeanFactory - getBeanFactory()

 

BeanFactory准备阶段

  • AbstractApplicationContext#prepareBeanFactory(ConfigurableListableBeanFactory)

关联 ClassLoader

设置Bean表达式处理器

添加 PropertyEditorRegistrar 实现 - ResourceEditorRegistrar

添加 Aware 回调接口 BeanPostProcessor 实现 - ApplicationContextAwareProcessor

忽略 Aware 回调接口作为依赖注入接口

注册 ResolvableDependency 对象 - BeanFactory、ResourceLoader、ApplicationEventPublisher 以及 ApplicationContext

注册 ApplicationListenerDetector 对象

注册 LoadTimeWeaverAwareProcessor 对象

注册单例对象 - Environment、Java System Properties 以及 OS 环境变量

 

BeanFactory 后置处理阶段

  • AbstractApplicationContext#postProcessBeanFactory(ConfigurableListableBeanFactory) 方法

由子类覆盖该方法

  • AbstractApplicationContext#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory)方法

调用 BeanFactoryPostProcessor 或 BeanDefinitionRegistry 后置处理方法

注册 LoadTimeWeaverAwareProcessor 对象

 

BeanFactory 注册 BeanPostProcessor 阶段

  • AbstractApplicationContext#registerBeanPostProcessors(ConfigurableListableBeanFactory) 方法

注册 PriorityOrdered 类型的 BeanPostProcessor Beans

注册 Ordered 类型的BeanPostProcessor Beans

注册普通 BeanPostProcessor Beans

注册 MergedBeanDefinitionPostProcessor Beans

注册 ApplicationListenerDetector 对象

 

初始化内建Bean:MessageSource

AbstractApplicationContext#initMessageSource() 方法

 

初始化内建Bean:Spring 事件广播器

AbstractApplicationContext#initApplicationEventMulticaster() 方法

 

Spring 应用上下文刷新阶段

  • AbstractApplicationContext#onRefresh() 方法

子类覆盖该方法

  • org.springframework.web.context.support.AbstractRefreshableWebApplicationContext#onRefresh()
  • org.springframework.web.context.support.GenericWebApplicationContext#onRefresh()
  • org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext#onRefresh()
  • org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh()
  • org.springframework.web.context.support.StaticWebApplicationContext#onRefresh()

 

Spring 事件监听器注册阶段

  • AbstractApplicationContext#registerListeners() 方法
  • 添加当前应用上下文所关联的ApplicationListener 对象(集合)
  • 添加BeanFactory 所注册 ApplicationListener Beans
  • 广播早期 Spring 事件

 

BeanFactory 初始化完成阶段

  • AbstractApplicationContext#finishBeanFactoryInitialization(ConfigurableListableBeanFactory) 方法
  • BeanFactory 关联 ConversionService Bean,如果存在
  • 添加 StringValueResolver 对象
  • 依赖查找 LoadTimeWeaverAware Bean
  • BeanFactory 临时 ClassLoader 置为 null
  • BeanFactory 冻结配置
  • BeanFactory 初始化非延迟单例Beans

 

Spring 应用上下文刷新完成阶段

  • AbstractApplicationContext#finishRefresh() 方法
  • 清除 ResourceLoader 缓存 - clearResourceCaches() @since 5.0
  • 初始化 LifecycleProcessor 对象 - initLifecycleProcessor()
  • 调用LifecycleProcessor#onRefresh() 方法
  • 发布Spring 应用上下文已刷新事件 - ContextRefreshedEvent
  • 向MBeanServer 托管 Live Beans

 

Spring 应用上下文启动阶段

  • AbstractApplicationContext#start()方法
  • 启动 LifecycleProcessor

依赖查找Lifecycle Bean

启动Lifecycle Beans

  • 发布Spring 应用上下文已启动事件 - ContextStartedEvent

 

Spring 应用上下文停止阶段

  • AbstractApplicationContext#stop()方法
  • 停止LifecycleProcessor

依赖查找 Lifecycle Bean

停止 Lifecycle Beans

  • 发布Spring 应用上下文已停止事件 - ContextStoppedEvent

 

Spring 应用上下文关闭阶段

  • AbstractApplicationContext#close() 方法
  • 状态标识:active(false)、closed(true)
  • Live Beans JMX 撤销托管

LiveBeansView.unregisterApplicationContext(ConfigurableApplicationContext)

  • 发布Spring 应用上下文已关闭事件 - ContextClosedEvent
  • 关闭 LifecycleProcessor

依赖查找 Lifecycle Beans

停止 Lifecycle Beans

  • 销毁 Spring Beans
  • 关闭 BeanFactory
  • 回调 onClose()
  • 注册 Shutdown Hook 线程(如果有注册)

 

Spring 应用上下文生命周期有哪些阶段?

  • 刷新阶段 - ConfigurableApplicationContext#refresh()
  • 启动阶段 - ConfigurableApplicationContext#start()
  • 停止阶段 - ConfigurableApplicationContext#stop()
  • 关闭阶段 - ConfigurableApplicationContext#close()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值