Spring源码
核心注解
注解 | 功能 |
---|---|
@Bean | 容器中注册组件 |
@Primary | 同类组件如果有多个,标注主组件 |
@DependsOn | 组件之间声明依赖关系 |
@Lazy | 组件懒加载(使用的时候才会创建) |
@Scope | 声明组件的作用域(SCOPE_PROTOTYPE,SCOPE_SINGLETON) |
@Configuration | 声明这是一个配置类,替换配置文件 |
@Component | @Controller、@Service、@Repository |
@Indexed | 加速注解,标注了@Indexed的组件,直接会启动快速加载 |
@Order | 数字越小优先级越高,越先工作 |
@ComponentScan | 包扫描 |
@Conditional | 条件注入 |
@Import | 导入第三方Jar包中的组件,或定制批量导入组件逻辑 |
@ImportResource | 导入以前的xml配置文件,让其生效 |
@Profile | 基于多环境激活 |
@PropertySource | 外部properties配置文件和JavaBean进行绑定,结合ConfigurationProperties |
@PropertySource | @PropertySource组合注解 |
@Autowired | 自动装配,默认按类型装配 |
@Qualifier | 精确指定,默认按名称装配 |
@Resource | 来自于JSR-250,非Spring提供,默认按名称装配 |
@Value | 取值、计算机环境变量、JVM系统。@Value(“${XX}”) |
@Lookup | 单例组件依赖非单例组件,非单例组件获取需要使用方法 |
Resource&ResourceLoader
Resource
需要处理不同类型的外部资源(URL、File、ClassPath等等),而且处理这些资源步骤都是类似的(打开资源,读取资源,关闭资源)。Spring提供Resource接口来统一这些底层资源一致的访问,作为所有资源的统一抽象。
Resource体系
Resource
1 | public interface Resource extends InputStreamSource { |
- ByteArrayResource:对于字节数组的实现,为其构造一个ByteArrayInputStream;
- ClassPathResource:ClassPath类型资源的实现,使用指定的Class或ClassLoader加载资源。用来访问类加载路径下的资源,该种类型在Web应用中可以自动搜索位于WEB-INF/classes下的资源文件,而无需使用绝对路径访问;
- InputStreamResource:InputStream的实现,如果需要将资源描述符保存在某处,或者如果需要从流中多次读取,不要使用InputStreamResource;
- UrlResource:对于java.net.URL类型资源的实现,支持File和URL的形式,既可以访问网络资源,也可以访问本地资源,加不同的前缀即可;
- FileSystemResource:对java.io.File类型和java.nio.file.Path资源的封装,支持File和URL的形式。实现了WritableResource接口,支持对资源的写操作;
- EncodedResource:实现对文件编码类型的处理。
它们都继承抽象类AbstractResource,AbstractResource实现了Resource接口。自定义Resource只需继承AbstractResource抽象类,它已经实现Resource接口的大部分公共实现,再根据自定义的资源特性覆盖相应的方法。
ResourceLoader
Resource定义统一的资源,ResourceLoader加载资源。
ResourceLoader体系
DefaultResourceLoader
1 | public class DefaultResourceLoader implements ResourceLoader { |
ProtocolResolver
用户自定义协议资源解决策略,作为DefaultResourceLoader的SPI,允许用户自定义资源加载协议,而不需要继承ResourceLoader的子类。实现ProtocolResolver接口。
1 | public class MyProtocolResolver implements ProtocolResolver { |
ResourcePatternResolver——ResourceLoader接口的增强
1 | public interface ResourcePatternResolver extends ResourceLoader { |
PatchMatchingResourcePatternResolver
ResourcePatternResolver最常用的子类
1 | public class PathMatchingResourcePatternResolver implements ResourcePatternResolver { |
ApplicationContext&BeanFactory
BeanFactory
BeanFactory体系
BeanFactory
BeanFactory是访问Spring中Bean容器的顶级接口,提供了IOC容器应遵守的最基本的接口。
1 | public interface BeanFactory { |
有3个接口直接继承了BeanFactory:HierarchicalBeanFactory、ListableBeanFactory、AutowireCapableBeanFactory。
HierarchiaclBeanFactory
增加了层级结构管理的功能,通过ConfigurableBeanFactory接口中的setParentBeanFactory,允许配置父BeanFactory。
1 | public interface HierarchicalBeanFactory extends BeanFactory { |
ListableBeanFactory
可以列表所有内部定义的bean。
1 | public interface ListableBeanFactory extends BeanFactory { |
AutowireCapableBeanFactory
增加了自动装配Bean属性依赖的能力,提供多种自动装配策略和细粒度控制装配过程的方法。
ConfigurableBeanFactory
扩展自HierarchicalBeanFactory和SingletonBeanRegistry,提供了对BeanFactory的配置能力。扩展的内容:类加载器、类型转换、属性编辑器、BeanPostProcessor、作用域、bean定义,处理bean依赖关系等。
ConfigurableListableBeanFactory
继承自上面3个接口,接口的集大成者。提供了分析和修改BeanDefinition以及预实例化单例的工具。、
抽象类
AbstractBeanFactory:实现了ConfigurableBeanFactory大部分功能;
AbstractAutowireCapableBeanFactory:继承自AbatractBeanFactory,并额外实现了AutowireCapableBeanFactory。
实现类
DefaultListableBeanFactory继承自AbstractAutowireCapableBeanFactory,并实现了ConfigurableListableBeanFactory和BeanDefinitionRegistry。
ApplicationContext
ApplicationContext扩展自ResourcePatternResolver、ListableBeanFactory、HierarchicalBeanFactory、MessageSource、ApplicationEventPublisher、EnvironmentCapable。ApplicationContext接口作为BeanFactory的派生,因而提供BeanFactory所有的功能,而且ApplicationContext还在功能上做了扩展。有如下功能:
- 发现、定义、维护、管理Bean;
- 可以向外界暴露当前程序所运行的环境信息;
- 国际化;
- 事件发布/订阅;
- 解析资源;
- 层次化上下文;
- 一些context可能通过持有AutowireCapableBeanFactory来支持自动装载能力。
ApplicationContext体系
ConfigurableApplicationContext
提供了配置ApplicationContext的功能。配置和生命周期方法被封装在这里,以避免它们对使用ApplicationContext的代码可见。
AbstractApplicationContext
模板模式:模板方法定义为 final,可以避免被子类重写。需要子类重写的方法定义为 abstract,可以强迫子类去实现。
refresh:加载或刷新配置
1 | public abstract class AbstractApplicationContext extends DefaultResourceLoader |
ClassPathXmlApplicationContext
通过读取类路径下的xml配置文件来构建ApplicationContext
1 | public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext { |
XmlBeanDefinitionReder
自动扫描和自动装配的功能都是context命名空间提供的。
1 | public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader { |
ContextNamespaceHandler
1 | public class ContextNamespaceHandler extends NamespaceHandlerSupport { |
NamespaceHandlerSupport
策略模式+模板模式
NamespaceHolder继承了NamespaceHolderSupport,可以通过注册BeanDefinitionParser和BeanDefinitionDecorator来解析对应的XML节点,执行需要的功能,注册该功能返回的BeanDefinition。
ComponentScanBeanDefinitionParser
使用component-scan时的自动装配功能并不是BeanFactory实现的,它通过为BeanDefinition设置默认值,完全禁用了每一个Bean的自动装配功能,取而代之的是,它通过BeanPostProcessor拦截Bean的生命周期实现仅对具有@Autowired注解的属性注入。
1 | public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider { |
ClassPathBeanDefinitionScanner
1 | /** |
总结
ClassPathXmlApplicationContext
默认并不带自动装配功能,它只通过XML中定义的结构去解析并生成BeanDefinition;- 自动装配功能由
context
命名空间提供; context
命名空间的组件扫描功能为每一个扫描到的组件都定义了它BeanDefinition的默认值,并在关闭了它的自动装配功能;context
命名空间通过向ApplicationContext中添加BeanPostProcessor
Bean来向底层BeanFactory中注册一批BeanPostProcessor,这其中包括用于实现自动装配的AutowiredAnnotationBeanPostProcessor
;AutowiredAnnotationBeanPostProcessor
是一个实例化感知BeanPostProcessor,它重写postProcessProperties
方法和postProcessPropertyValues
方法,拦截了Bean初始化阶段的属性设置post-processing。它对于每一个包含@Value
、@Autowired
、@Inject
注解的属性,通过调用BeanFactory中的resolveDependency
来获得需要被注入的Bean或值,并注入进被拦截的Bean中。
ApplicationContext与BeanFactory的区别
- BeanFactory是IOC底层容器,面向Spring;ApplicationContext是具备应用特性的BeanFactory超集,面向使用 Spring框架的开发者。额外提供AOP、资源管理、国际化、事件、Environment抽象等功能;
- BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化;ApplicationContext则在容器启动时,就实例化Bean,常驻在容器内,也可以为Bean配置Lazy-init=true来让Bean延迟实例化。
BeanDefinition
Spring容器启动的过程中,会将Bean解析成Spring内部的BeanDefinition结构。 不管是是通过xml配置文件的\<Bean>
标签,还是通过注解配置的@Bean,它最终都会被解析成一个Bean定义信息(对象),最后我们的Bean工厂就会根据这份Bean的定义信息,对bean进行实例化、初始化等等操作
BeanDefinition
Spring中Bean的定义,包含Bean的元数据信息:对应的bean的全限定类名,属性值,构造方法参数值和继承自它的类的更多信息。
1 | public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement { |
BeanDefinition体系
AttributeAccessor
为其它任意类中获取或设置元数据提供了一个通用的规范。具体实现是AttributeAccessorSupport,采用LinkedHashMap进行存储。
BeanMetadataDefinition
提供了getSource(),返回Bean的来源。
抽象实现
AbstractBeanDefinition
抽象类,BeanDefinition定义了一系列的get/set方法,并没有提供对应的属性。AbstractBeanDefinition中将所有的属性定义出来了。
RootBeanDefinition
Spring去创建Bean就是基于RootBeanDefinition,在AbstractBeanDefinition的基础上扩展一些之外的功能。
ChildBeanDefinition
不可以单独存在,必须依赖一个父BeanDefinition。构造ChildBeanDefinition时,其构造方法传入父BeanDefinition的名称或通过setParentName设置父BeanDefinition名称。它可以从父类继承方法参数、属性值,并可以重写父类的方法,同时也可增加新的属性或者方法。
Spring2.5之后,逐渐被GenericBeanDefinition替代。
GenericBeanDefinition
GenericBeanDefinition 可以动态设置父 Bean,同时兼具 RootBeanDefinition 和 ChildBeanDefinition 的功能。通过注解配置的bean以及XML配置的BeanDefinition类型都是GenericBeanDefinition。
子接口
AnnotatedBeanDefinition
表示注解类型 BeanDefinition,拥有获取注解元数据和方法元数据的能力。
1 | public interface AnnotatedBeanDefinition extends BeanDefinition { |
AnnotatedGenericBeanDefinition
xxxBeanDefinitionReader加载的BeanDefinition
继承自GenericBeanDefinition并实现了AnnotatedBeanDefinition接口,使用了 @Configuration 注解标记配置类会解析为 AnnotatedGenericBeanDefinition。
ScannedGenericBeanDefinition
ClassPathBeanDefinitionScanner加载的BeanDefinition
实现了 AnnotatedBeanDefinition也继承了 GenericBeanDefinition。使用了@Component、@Service、@Controller等注解类会解析为 ScannedGenericBeanDefinition。
ConfigurationClassBeanDefinition
ConfigurationClassBeanDefinitionReader的一个使用静态内部类,负责将使用了@Bean的方法转换为ConfigurationClassBeanDefinition 类。
Spring初始化时,会用GenericBeanDefinition或是ConfigurationClassBeanDefinition(用@Bean注解注释的类)存储用户自定义的Bean,在初始化Bean时,又会将其转换为RootBeanDefinition。
扩展
BeanDefinitionBuilder
快速创建一个BeanDefinition,可以进行链式的方法调用,建造者模式,默认是GenericBeanDefinition。
1 | public class Demo { |
BeanDefinitionReader
读取Spring配置文件中的内容,将其转换为IOC容器内的数据结构BeanDefinnition。
1 | public interface BeanDefinitionReader { |
AbstractBeanDefinitionReader
实现了EnvironmentCapable,提供了获取/设置环境的方法。实现一些基本方法,通过策略模式核心方法loadBeanDefinitions交给子类实现。
XmlBeanDefinitionReader
继承了 AbstractBeanDefinitionReader 所有的方法,同时也扩展了很多新的方法,主要用于读取 XML 文件中定义的 bean。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public class Demo {
public static void main(String[] args) {
// 1.获取资源
ClassPathResource resource = new ClassPathResource("spring-config.xml");
// 2.获取BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 3.根据新建的BeanFactory创建一个BeanDefinitionReader对象,用于资源解析
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 4.装载资源
// 4.1 资源定位
// 4.2 装载:BeanDefinitionReader读取、解析Resource资源,也就是将用户定义的Bean表示成IOC容器的内部数据结构:BeanDefinition。
// 4.3 注册:向IOC容器注册在第二步解析好的BeanDefinition,这个过程是通过BeanDefinitionRegistry接口来实现的。
// 本质上是将解析得到的BeanDefinition注入到一个HashMap容器中,IOC容器就是通过这个HashMap来维护这些BeanDefinition的。
// 注意:此过程并没有完成依赖注入,依赖注册是发生在应用第一次调用getBean()向容器索要Bean时。(可以通过设置预处理,即对某个Bean设置lazyInit属性)
beanDefinitionReader.loadBeanDefinitions(resource);
Person person = beanFactory.getBean(Person.class);
System.out.println(person);
}
}PropertiesBeanDefinitionReader
从properties文件或者Map里加载Bean。
GroovyBeanDefinitionReader
可以读取 Groovy 语言定义的 Bean。
@Bean是@Configuration,统一由ConfigurationClassParser#parse()处理;
@Component这种组件统一由解析@ComponentScan的处理器的ComponentScanAnnotationParser(借助ClassPathBeanDefinitionScanner)。
Aware
有时需要感知到容器的存在,获取容器相关信息,Spring提供许多实现Aware接口的类,这些类主要是为了辅助Spring访问容器中的数据。
常见的Aware接口
类名 | 作用 |
---|---|
BeanNameAware | 获得容器中Bean名称 |
BeanClassLoaderAware | 获得类加载器 |
BeanFactoryAware | 获得Dean创建工厂 |
EnvironmentAware | 获得环境变量 |
EmbeddedValueResolverAware | 获得Spring容器加载的Properties文件属性值 |
ResourceLoaderAware | 获得资源加载器 |
ApplicationEventPublishAware | 获得应用事件发布器 |
MessageSourceAware | 获得文本信息 |
ApplicationContextAware | 获得当前应用上下文 |
Aware调用链
AbstractAutowireCapableBeanFactory#createBean()
===> AbstractAutowireCapableBeanFactory#doCreateBean()
===>AbstractAutowireCapableBeanFactory#initializeBean()
===> AbstractAutowireCapableBeanFactory#invokeAwareMethods()
===> AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization()
===> ApplicationContextAwareProcessor#postProcessBeforeInitialization()
===> ApplicationContextAwareProcessor#invokeAwareInterfaces()
自定义Aware
新建接口继承Aware
1
2
3public interface MyBeanNameAware extends Aware {
void setBeanName(String name);
}新建一个BeanPostProcessor实现类,重新postProcessBeforeInitialization处理自定义的Aware
1
2
3
4
5
6
7
8
9
10
11
public class MyBeanNameAwareProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof MyBeanNameAware){
((MyBeanNameAware) bean).setBeanName(beanName);
}
return bean;
}
}使用
1
2
3
4
5
6
7
8
9
10
11
public class UserService implements MyBeanNameAware {
private String beanName;
public void test(){
System.out.println("test" + "___" + this.beanName);
}
public void setBeanName(String name) {
this.beanName = name;
}
}
BeanFactoryPostProcessor
BeanFactory的后置处理器,用来对BeanFactory进行加工。
修改已经注册的beanDefinition的元信息。发生在Spring启动时,实例化单例Bean之前。
1 |
|
在ApplicationContext内部有一个核心的DefaultListableBeanFactory,实现了ConfigurableListableBeanFactory和BeanDefinitionRegistry接口,所以ApplicationContext和DefaultListableBeanFactory是可以注册BeanDefinition的,但是ConfigurableListableBeanFactory是不能注册BeanDefinition的,只能获取BeanDefinition,然后做修改。
BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor,所以BeanDefinitionRegistryPostProcessor不仅提供postProcessBeanFactory(),方法还扩展了支持注册BeanDefinition的方法postProcessBeanDefinitionRegistry()
1 |
|
BeanFactoryPostProcessor调用链
AbstractApplicationContext#refresh()
===> AbstractApplicationContext#invokeBeanFactoryPostProcessors()
===> PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()
===> PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()
===> BeanFactoryPostProcessor#postProcessBeanFactory()
InitializingBean、DisposableBean
Spring 开放了扩展接口,允许自定义 bean 的初始化和销毁方法。即当 Spring 容器在 bean 进行到相应的生命周期阶段时,会自动调用我们自定义的初始化和销毁方法。这两个扩展接口即是 InitializingBean
和 DisposableBean
。
InitializingBean
1 | public interface InitializingBean { |
InitializingBean与SmartInitialzingSingleton的区别
SmartInitialzing只作用于单例Bean,InitialzingBean无此要求;
SmartInitialzing是在所有的非懒加载单例Bean初始化完成后调用,InitialzingBean在每个Bean初始化后调用。
InitialzingBean调用源码:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd)
throws Throwable {
//是否实现了initializingBean接口
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//执行自定义的afterPropertiesSet()
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {
//反射调用指定的initMethod
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}SmartInitialzingBean调用源码:org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public void preInstantiateSingletons() throws BeansException {
// 触发所有非延迟加载单例 Bean 的初始化
......
//触发所有 SmartInitializingSingleton 后初始化的回调
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}
DisposableBean
DisposableBean 接口为
单例 bean
提供了在容器销毁 bean 时的处理方法,在 bean 被销毁时都会执行重写了的destroy()。1
2
3public interface DisposableBean {
void destroy() throws Exception;
}调用源码:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#destroyBean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15protected void destroyBean(String beanName, { DisposableBean bean)
......
if (bean != null) {
try {
//执行destroy
bean.destroy();
}
catch (Throwable ex) {
if (logger.isWarnEnabled()) {
logger.warn("Destruction of bean with name '" + beanName + "' threw an exception", ex);
}
}
}
......
}
Spring Factories
Spring Factories是一种类似于Java SPI的机制,在resources/META-INF/spring.factories文件中配置接口的实现类名称(接口名称=实现类),然后在程序中读取该配置文件并实例化,是spring-boot-starter-xxx的实现基础。
为什么需要spring.factories?
如果想要被Spring容器管理的Bean的路径不在spring-boot项目的扫描路径下,该怎么办呢?
解耦容器注入,帮助外部包(独立于spring-boot项目)注册Bean到spring-boot项目中。
实现原理
org.springframework.core.io.support.SpringFactoriesLoader
1 | //按接口获取spring.fatories文件中的实现类的实例 |
调用链路:org.springframework.boot.SpringApplication#SpringApplication()
==>org.springframework.boot.SpringApplication#getSpringFactoriesInstances()
==>org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames
==>org.springframework.core.io.support.SpringFactoriesLoader#loadSpringFactories
例子
从数据库加载配置:
1 | public class DatabaseEnvironmentPostProcessor implements EnvironmentPostProcessor { |
spring.factories:
1 | org.springframework.boot.env.EnvironmentPostProcessor=\ |
参考:https://juejin.cn/post/7113166186849763358