Spring源码

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
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
public interface Resource extends InputStreamSource {

/**
* 当前Resource资源是否存在
*/
boolean exists();

/**
* 当前Resource是否可读
*/
default boolean isReadable() {
return exists();
}

/**
* 当前Resource是否已经打开,如果返回true,则只能被读取一次然后关闭以避免资源泄露;
* 常见的Resource实现一般返回false
*/
default boolean isOpen() {
return false;
}

/**
* 是否为文件资源
*/
default boolean isFile() {
return false;
}

/**
* 如果当前Resource代表的资源能由java.util.URL代表,则返回该URL,否则抛出IOException
*/
URL getURL() throws IOException;

/**
* 如果当前Resource代表的资源能由java.util.URI代表,则返回该URL,否则抛出IOException
*/
URI getURI() throws IOException;

/**
* 如果当前Resource代表的底层资源能由java.io.File代表,则返回该File,否则抛出IOException
*/
File getFile() throws IOException;

default ReadableByteChannel readableChannel() throws IOException {
return Channels.newChannel(getInputStream());
}

/**
* 返回当前Resource代表的底层文件资源的长度,一般是值代表的文件资源的长度
*/
long contentLength() throws IOException;

/**
* 返回当前Resource代表的底层资源的最后修改时间
*/
long lastModified() throws IOException;

Resource createRelative(String relativePath) throws IOException;

/**
* 返回当前Resource代表的底层文件资源的文件路径,比如File资源“file://d:/test.txt”将返回“d:/test.txt”;
* 而URL资源http://www.baidu.cn将返回null,因为只返回文件路径
*/
@Nullable
String getFilename();

/**
* 返回当前Resource代表的底层资源的描述符,通常就是资源的全路径(实际文件名或实际URL地址)
*/
String getDescription();
}
  • 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
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
public class DefaultResourceLoader implements ResourceLoader {
......
@Override
public Resource getResource(String location) {
Assert.notNull(location, "Location must not be null");
// 是否有自定义协议策略
for (ProtocolResolver protocolResolver : getProtocolResolvers()) {
Resource resource = protocolResolver.resolve(location, this);
if (resource != null) {
return resource;
}
}
// 以“/”开头,构造返回ClassPathContextResource
if (location.startsWith("/")) {
return getResourceByPath(location);
}
else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
// 以"classpath:"开头,构造返回ClassPathResource
return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
}
else {
// 否则构造URL地址
try {
URL url = new URL(location);
// 如果是FileURL,构造返回FileUrlResource,否则构造返回UrlResource
return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
}
catch (MalformedURLException ex) {
//构造URL失败(不符合URL规范),当作普通路径处理
return getResourceByPath(location);
}
}
}
......
}

ProtocolResolver

用户自定义协议资源解决策略,作为DefaultResourceLoader的SPI,允许用户自定义资源加载协议,而不需要继承ResourceLoader的子类。实现ProtocolResolver接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class MyProtocolResolver implements ProtocolResolver {

@Override
public Resource resolve(String location,
ResourceLoader resourceLoader) {
System.out.println("自定义加载资源......");
FileSystemResourceLoader fileSystemResourceLoader = new FileSystemResourceLoader();
return fileSystemResourceLoader.getResource("D:\\IDEAProbject\\openSources\\spring-framework\\gradle\\docs.gradle");
}
}

public class Demo {
public static void main(String[] args) {
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
resourceLoader.addProtocolResolver(new MyProtocolResolver());
Resource resource = resourceLoader.getResource("/");
System.out.println(resource.getFilename()); //docs.gradle
System.out.println(resource.getDescription()); //file [D:\IDEAProbject\openSources\spring-framework\gradle\docs.gradle]
}
}

ResourcePatternResolver——ResourceLoader接口的增强

1
2
3
4
5
6
7
8
9
10
11
public interface ResourcePatternResolver extends ResourceLoader {
/**
* 支持classpath*:形式路径匹配,即Ant风格;允许使用通配符来对路径进行匹配。"classpath*:"可以返回路径下所有满足条件的资源实例
*/
String CLASSPATH_ALL_URL_PREFIX = "classpath*:";

/**
* 支持根据路径匹配模式返回多个 Resource 实例
*/
Resource[] getResources(String locationPattern) throws IOException;
}

PatchMatchingResourcePatternResolver

ResourcePatternResolver最常用的子类

1
2
3
4
5
6
7
8
9
10
11
12
public class PathMatchingResourcePatternResolver implements ResourcePatternResolver {
// 负责对基于字符串的路径和指定的模式符号进行匹配
private PathMatcher pathMatcher = new AntPathMatcher();
/**
* 实例化一个DefaultResourceLoader,继承自ResourceLoader的方法委托给内部的DefaultResourceLoader实现
* PathMatchingResourcePatternResolver只负责处理实现ResourcePatternResolver中的方法
*/
public PathMatchingResourcePatternResolver() {
this.resourceLoader = new DefaultResourceLoader();
}

}

ApplicationContext&BeanFactory

BeanFactory

BeanFactory体系

BeanFactory

BeanFactory是访问Spring中Bean容器的顶级接口,提供了IOC容器应遵守的最基本的接口。

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
public interface BeanFactory {
/**
* FactoryBean实例前缀,如bean的名称为myJndiObject,并且该bean是FactoryBean,则获得&myJndiObject的bean时会返回Factory而不是Factory返回的实例
*/
String FACTORY_BEAN_PREFIX = "&";

/**
* 返回指定名称的bean
* 如果name是别名,最终会转换回真实的名称;
* 如果本Factory实例没找到,会询问父Factory查找;
* 未找到抛出BeansException
*/
Object getBean(String name) throws BeansException;

/**
* 与{@link #getBean(String)}类似,增加类型校验,如果类型异常抛出BeanNotOfRequiredTypeException
*/
<T> T getBean(String name, Class<T> requiredType) throws BeansException;

/**
* 通过给定的参数匹配构造函数或者工厂方法创建给定名称的实例。
*/
Object getBean(String name, Object... args) throws BeansException;

/**
* 按类型获取唯一Bean
*/
<T> T getBean(Class<T> requiredType) throws BeansException;

/**
* 通过给定的参数匹配构造函数或者工厂方法创建给定类型的实例。
*/
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

/**
* 返回指定Bean的Provider,允许延迟按需检索实例
*/
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);

<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);

/**
* 是否存在指定名称的bean
* 如果本Factory实例没找到,会询问父Factory查找;
*/
boolean containsBean(String name);

/**
* 判断name对应的bean是否为单例的
*/
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

/**
* 判断name对应的bean是否为原型作用域
*/
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

/**
* 判断name对应的bean与指定的类型是否匹配,更具体来说就是判断getBean方法返回的对象与目标类型是否匹配
* ResolvableType.forClass(XXXX.class)))
*/
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

/**
* 判断name对应的bean与指定的类型是否匹配
*/
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

/**
* 根据name获取其对应的bean的类型
*/
@Nullable
Class<?> getType(String name) throws NoSuchBeanDefinitionException;

/**
* 根据name获取其对应的bean的类型。指定是否允许FactoryBean初始化
*/
@Nullable
Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;

/**
* 返回指定名称的所有别名信息,如果name是别名,返回原始名和其他笔名,原始名在数组的第一个元素
*/
String[] getAliases(String name);
}

有3个接口直接继承了BeanFactory:HierarchicalBeanFactory、ListableBeanFactory、AutowireCapableBeanFactory。

HierarchiaclBeanFactory

增加了层级结构管理的功能,通过ConfigurableBeanFactory接口中的setParentBeanFactory,允许配置父BeanFactory。

1
2
3
4
5
6
7
8
9
10
11
12
public interface HierarchicalBeanFactory extends BeanFactory {
/**
* 返回当前BeanFactory的父BeanFactory,如果没有返回null
*/
@Nullable
BeanFactory getParentBeanFactory();

/**
* 返回本BeanFactory是否包含指定namne的bean,不考虑父BeanFactory
*/
boolean containsLocalBean(String name);
}

ListableBeanFactory

可以列表所有内部定义的bean。

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
public interface ListableBeanFactory extends BeanFactory {
/**
* 判断BeanFactory是否含给定名称的Bean定义,并不考虑层次结构,并忽略通过Bean定义以外方式注册的单例Bean
*/
boolean containsBeanDefinition(String beanName);

/**
* 获取BeanFactory中已经定义的Bean数量,并不考虑层次结构,并忽略通过Bean定义以外方式注册的单例Bean
*/
int getBeanDefinitionCount();

/*
* 返回本BeanFactory中所有Bean定义的名称
*/
String[] getBeanDefinitionNames();

/**
* 返回指定Bean的提供者,支持延迟初始化
*/
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType, boolean allowEagerInit);

<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType, boolean allowEagerInit);

String[] getBeanNamesForType(ResolvableType type);

/**
* 返回与给定类型及子类匹配的bean的名称
* allowEagerInit 是否初始化FactoryBean。如果为false,会检查原始的FactoryBean是否与给定类型匹配,不考虑任何层次结构
*/
String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit);

String[] getBeanNamesForType(@Nullable Class<?> type);

String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);

/**
* 通过给定的类型获取其对应的bean实例,其中map的key是bean的名称,value是该bean对应的实例
*/
<T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException;

<T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
throws BeansException;

/**
* 查找包含给定注解的bean的名称,而不创建对应的bean实例
*/
String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);

/*
* 查找包含给定注解的bean名称,并创建对应的bean实例,其中返回的map中key为bean名称,value为bean的实例
*/
Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;

/**
* 在给定name的bean上面查找是否包含给定的注解,如果包含则返回该注解,不包含则返回null
* 通过此方法可以获得给定bean的注解,并获取其注解中对应的值
*/
@Nullable
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
throws NoSuchBeanDefinitionException;
@Nullable
<A extends Annotation> A findAnnotationOnBean(
String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
throws NoSuchBeanDefinitionException;
}

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还在功能上做了扩展。有如下功能:

  1. 发现、定义、维护、管理Bean;
  2. 可以向外界暴露当前程序所运行的环境信息;
  3. 国际化;
  4. 事件发布/订阅;
  5. 解析资源;
  6. 层次化上下文;
  7. 一些context可能通过持有AutowireCapableBeanFactory来支持自动装载能力。

ApplicationContext体系

ConfigurableApplicationContext

提供了配置ApplicationContext的功能。配置和生命周期方法被封装在这里,以避免它们对使用ApplicationContext的代码可见。

AbstractApplicationContext

模板模式:模板方法定义为 final,可以避免被子类重写。需要子类重写的方法定义为 abstract,可以强迫子类去实现。

refresh:加载或刷新配置

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
@Override
public void refresh() throws BeansException, IllegalStateException {
// 加锁:registerShutdownHook,close,refresh互斥
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

// Prepare this context for refreshing.
// 设置Spring容器的启动时间,撤销关闭状态,开启活跃状态
prepareRefresh();

// Tell the subclass to refresh the internal bean factory.
// 通知子类刷新内部factory并返回
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.
//准备BeanFactory以在此上下文中使用
prepareBeanFactory(beanFactory);

try {
// Allows post-processing of the bean factory in context subclasses.
// 后置处理BeanFactory
postProcessBeanFactory(beanFactory);

StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
//调用所有注册在context中的BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
//注册BeanPostProcessor后置处理器,这里的后置处理器在下方实例化Bean方法中会用到
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();

// Initialize message source for this context.
initMessageSource();

// Initialize event multicaster for this context.
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
//初始化特定子类上下文中的其它特殊bean(模板模式)
onRefresh();

// Check for listener beans and register them.
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
//实例化BeanFactory中已经被注册但是未实例化的所有Bean(懒加载的不需要实例化)。即生成环境所需要的Bean。
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
finishRefresh();
}

catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}

// Destroy already created singletons to avoid dangling resources.
destroyBeans();

// Reset 'active' flag.
cancelRefresh(ex);

// Propagate exception to caller.
throw ex;
}

finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
contextRefresh.end();
}
}
}
}

ClassPathXmlApplicationContext

通过读取类路径下的xml配置文件来构建ApplicationContext

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {

super(parent);
setConfigLocations(configLocations);
if (refresh) {
//refresh也会调用子类的相关方法以模板模式来完成整个刷新功能,刷新的最终结果就是beanfactory中被塞了一些context需要的bean和postprocessor,并且beandefinition被冻结,所有singleton被预实例化。
refresh();
}
}
}

XmlBeanDefinitionReder

自动扫描和自动装配的功能都是context命名空间提供的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
//获取一个命名空间处理器解析器
public NamespaceHandlerResolver getNamespaceHandlerResolver() {
if (this.namespaceHandlerResolver == null) {
this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
}
return this.namespaceHandlerResolver;
}

protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader());
return new DefaultNamespaceHandlerResolver(cl); //META-INF/spring.handlers
}
}

ContextNamespaceHandler

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ContextNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); //组件自动扫描
registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}
}

NamespaceHandlerSupport

策略模式+模板模式

NamespaceHolder继承了NamespaceHolderSupport,可以通过注册BeanDefinitionParser和BeanDefinitionDecorator来解析对应的XML节点,执行需要的功能,注册该功能返回的BeanDefinition。

ComponentScanBeanDefinitionParser

使用component-scan时的自动装配功能并不是BeanFactory实现的,它通过为BeanDefinition设置默认值,完全禁用了每一个Bean的自动装配功能,取而代之的是,它通过BeanPostProcessor拦截Bean的生命周期实现仅对具有@Autowired注解的属性注入。

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
36
37
38
39
40
41
42
43
44
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
/**
* 给basePackage包下所有@Component标注的类创建BeanDefinition,应用默认BeanDefinition设置,
* 并且检查Bean类上的一些注解,对BeanDefinition进行对应设置,如@Lazy注解。
* 最后,它会将BeanDefinition包装成BeanDefinitionHolder,并返回Holder列表。
* 而且,该方法已经向BeanFactoryRegistry注册了BeanDefinition。
*/
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
//初始化BeanDefinition集合
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
//扫描所有basePackage
for (String basePackage : basePackages) {
//候选组件
//使用自带的默认AnnotationTypeFilter来过滤basePackage指定的所有包下具有@Component注解的组件
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
//设置作用域
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
//bean名称
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
//检测是否具有@Lazy、@Primary、@DependsOn、@Role、@Description注解,如果有就向BeanDefinition中设置对应的配置
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
//将BeanDefinition以及生成的beanName包装到BeanDefinitionHolder中
//BeanDefinitionHolder中封装了BeanDefinition和它的BeanName、别名等信息
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
//向registry中注册BeanDefinition
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
}

ClassPathBeanDefinitionScanner

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
36
37
38
39
40
41
42
/**
* 给basePackage包下所有@Component标注的类创建BeanDefinition,应用默认BeanDefinition设置,
* 并且检查Bean类上的一些注解,对BeanDefinition进行对应设置,如@Lazy注解。
* 最后,它会将BeanDefinition包装成BeanDefinitionHolder,并返回Holder列表。
* 而且,该方法已经向BeanFactoryRegistry注册了BeanDefinition。
*/
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
//初始化BeanDefinition集合
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
//扫描所有basePackage
for (String basePackage : basePackages) {
//候选组件
//使用自带的默认AnnotationTypeFilter来过滤basePackage指定的所有包下具有@Component注解的组件
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
//设置作用域
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
//bean名称
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
//检测是否具有@Lazy、@Primary、@DependsOn、@Role、@Description注解,如果有就向BeanDefinition中设置对应的配置
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
//将BeanDefinition以及生成的beanName包装到BeanDefinitionHolder中
//BeanDefinitionHolder中封装了BeanDefinition和它的BeanName、别名等信息
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
//向registry中注册BeanDefinition
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}

总结

  • ClassPathXmlApplicationContext默认并不带自动装配功能,它只通过XML中定义的结构去解析并生成BeanDefinition;
  • 自动装配功能由context命名空间提供;
  • context命名空间的组件扫描功能为每一个扫描到的组件都定义了它BeanDefinition的默认值,并在关闭了它的自动装配功能;
  • context命名空间通过向ApplicationContext中添加BeanPostProcessorBean来向底层BeanFactory中注册一批BeanPostProcessor,这其中包括用于实现自动装配的AutowiredAnnotationBeanPostProcessor
  • AutowiredAnnotationBeanPostProcessor是一个实例化感知BeanPostProcessor,它重写postProcessProperties方法和postProcessPropertyValues方法,拦截了Bean初始化阶段的属性设置post-processing。它对于每一个包含@Value@Autowired@Inject注解的属性,通过调用BeanFactory中的resolveDependency来获得需要被注入的Bean或值,并注入进被拦截的Bean中。

ApplicationContext与BeanFactory的区别

  1. BeanFactory是IOC底层容器,面向Spring;ApplicationContext是具备应用特性的BeanFactory超集,面向使用 Spring框架的开发者。额外提供AOP、资源管理、国际化、事件、Environment抽象等功能;
  2. 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
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

int ROLE_APPLICATION = 0;

int ROLE_SUPPORT = 1;

int ROLE_INFRASTRUCTURE = 2;

/**
* 如果父类存在,设置这个bean定义的父定义的名称。
*/
void setParentName(@Nullable String parentName);

@Nullable
String getParentName();

/**
* 指定此bean定义的bean类名称。
*/
void setBeanClassName(@Nullable String beanClassName);

@Nullable
String getBeanClassName();

/**
* 覆盖此bean的作用域,指定一个新的作用域。
*/
void setScope(@Nullable String scope);

@Nullable
String getScope();

/**
*设置这个bean是否应该被延迟初始化。如果false,那么这个bean将在启动时由bean工厂实例化,
* 懒加载 <bean lazy-init="true/false">
*/
void setLazyInit(boolean lazyInit);

boolean isLazyInit();

/**
* 设置这个bean依赖被初始化的bean的名字。 bean工厂将保证这些bean首先被初始化。
* <bean depends-on="">
*/
void setDependsOn(@Nullable String... dependsOn);

@Nullable
String[] getDependsOn();

/**
* 配置Bean是否是自动装配的候选者 默认为 true XML中的 <bean autowire-candidate="">
*/
void setAutowireCandidate(boolean autowireCandidate);

boolean isAutowireCandidate();

/**
* 如果找到了多个可注入bean,那么则选择被Primary标记的bean/获取当前 Bean 是否为首选的 Bean XML中的 <bean primary="">
*/
void setPrimary(boolean primary);

boolean isPrimary();

/**
* 配置FactoryBean的名字 XML中的<bean factory-bean="">
*/
void setFactoryBeanName(@Nullable String factoryBeanName);

@Nullable
String getFactoryBeanName();

/**
* 配置/获取 FactoryMethod 的名字,可以是某个实例的方法(和factoryBean配合使用)
* 也可以是静态方法。 XML 中的<bean factory-method="">
*/
void setFactoryMethodName(@Nullable String factoryMethodName);

@Nullable
String getFactoryMethodName();

/**
* 返回该 Bean 构造方法的参数值
*/
ConstructorArgumentValues getConstructorArgumentValues();

default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}

/**
* 获取普通属性的集合
*/
MutablePropertyValues getPropertyValues();

default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}

/**
* 配置 Bean 的初始化方法 XML中的<bean init-method="">
*/
void setInitMethodName(@Nullable String initMethodName);

@Nullable
String getInitMethodName();

/**
* 配置 Bean 的销毁方法 XML中的<bean destroy-method="">
*/
void setDestroyMethodName(@Nullable String destroyMethodName);

@Nullable
String getDestroyMethodName();

void setRole(int role);

int getRole();

void setDescription(@Nullable String description);

/**
* Return a human-readable description of this bean definition.
*/
@Nullable
String getDescription();


// Read-only attributes

/**
* Return a resolvable type for this bean definition,
* based on the bean class or other specific metadata.
* <p>This is typically fully resolved on a runtime-merged bean definition
* but not necessarily on a configuration-time definition instance.
* @return the resolvable type (potentially {@link ResolvableType#NONE})
* @since 5.2
* @see ConfigurableBeanFactory#getMergedBeanDefinition
*
* 用来解析一个Bean对应的类型上的各种信息,比如泛型
*/
ResolvableType getResolvableType();

/**
* Return whether this a <b>Singleton</b>, with a single, shared instance
* returned on all calls.
* @see #SCOPE_SINGLETON
*/
boolean isSingleton();

/**
* Return whether this a <b>Prototype</b>, with an independent instance
* returned for each call.
* @since 3.0
* @see #SCOPE_PROTOTYPE
*/
boolean isPrototype();

/**
* Return whether this bean is "abstract", that is, not meant to be instantiated.
*/
boolean isAbstract();

/**
* Return a description of the resource that this bean definition
* came from (for the purpose of showing context in case of errors).
*/
@Nullable
String getResourceDescription();

/**
* Return the originating BeanDefinition, or {@code null} if none.
* <p>Allows for retrieving the decorated bean definition, if any.
* <p>Note that this method returns the immediate originator. Iterate through the
* originator chain to find the original BeanDefinition as defined by the user.
* 如果当前 BeanDefinition 是一个代理对象,那么该方法可以用来返回原始的 BeanDefinition
*/
@Nullable
BeanDefinition getOriginatingBeanDefinition();

}

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
2
3
4
5
6
7
8
9
10
11
12
public interface AnnotatedBeanDefinition extends BeanDefinition {
/**
* 主要对 Bean 的注解信息进行操作,如:获取当前 Bean 标注的所有注解、判断是否包含指定注解。
*/
AnnotationMetadata getMetadata();

/**
* 方法的元数据类。提供获取方法名称、此方法所属类的全类名、是否是抽象方法、判断是否是静态方法、判断是否是final方法等。
*/
@Nullable
MethodMetadata getFactoryMethodMetadata();
}

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Demo {
public static void main(String[] args) {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
.genericBeanDefinition(User.class)
//Spring5.0后提供的,可以自己书写函数,在里面做任意事情
.applyCustomizers(
//bd是个AbstractBeanDefinition
(bd -> {
MutablePropertyValues propertyValues = bd.getPropertyValues();
propertyValues.add("name", "安卓");
})
).getBeanDefinition();
System.out.println(beanDefinition); //Generic bean: class [cn.BeanDefinition.RootBeanDefinition.User]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerBeanDefinition("user", beanDefinition);
User user = (User) beanFactory.getBean("user");
System.out.println(user); //User(name=安卓, age=null)
}

BeanDefinitionReader

读取Spring配置文件中的内容,将其转换为IOC容器内的数据结构BeanDefinnition。

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
public interface BeanDefinitionReader {

/**
* 得到Bean定义的register
*/
BeanDefinitionRegistry getRegistry();

/**
* 返回用于加载资源的 ResourceLoader(可以为null)
*/
@Nullable
ResourceLoader getResourceLoader();

/**
* 加载Bean的类加载器
*/
@Nullable
ClassLoader getBeanClassLoader();

/**
* 生成Bean名称的名字生成器(若没有指定名称的话,会调用它生成)
*/
BeanNameGenerator getBeanNameGenerator();


/**
* 核心方法,加载bean定义进来,然后注册到上面的register里面去
*/
int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException;
int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException;
int loadBeanDefinitions(String location) throws BeanDefinitionStoreException;
int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException;
}

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
    20
    public 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

  1. 新建接口继承Aware

    1
    2
    3
    public interface MyBeanNameAware extends Aware {
    void setBeanName(String name);
    }
  2. 新建一个BeanPostProcessor实现类,重新postProcessBeforeInitialization处理自定义的Aware

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Component
    public class MyBeanNameAwareProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
    throws BeansException {
    if (bean instanceof MyBeanNameAware){
    ((MyBeanNameAware) bean).setBeanName(beanName);
    }
    return bean;
    }
    }
  3. 使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Component
    public class UserService implements MyBeanNameAware {
    private String beanName;
    public void test(){
    System.out.println("test" + "___" + this.beanName);
    }
    @Override
    public void setBeanName(String name) {
    this.beanName = name;
    }
    }

BeanFactoryPostProcessor

BeanFactory的后置处理器,用来对BeanFactory进行加工。

修改已经注册的beanDefinition的元信息。发生在Spring启动时,实例化单例Bean之前。

1
2
3
4
5
6
7
8
9
10
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition userService = beanFactory.getBeanDefinition("userService");
userService.setScope(BeanDefinition.SCOPE_PROTOTYPE);
//...
}
}

在ApplicationContext内部有一个核心的DefaultListableBeanFactory,实现了ConfigurableListableBeanFactory和BeanDefinitionRegistry接口,所以ApplicationContext和DefaultListableBeanFactory是可以注册BeanDefinition的,但是ConfigurableListableBeanFactory是不能注册BeanDefinition的,只能获取BeanDefinition,然后做修改。

BeanDefinitionRegistryPostProcessor

BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor,所以BeanDefinitionRegistryPostProcessor不仅提供postProcessBeanFactory(),方法还扩展了支持注册BeanDefinition的方法postProcessBeanDefinitionRegistry()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {

}
@Override
public void postProcessBeanDefinitionRegistry(
BeanDefinitionRegistry registry) throws BeansException {
registry.registerBeanDefinition("1",
BeanDefinitionBuilder.genericBeanDefinition(OrderService.class)
.getBeanDefinition());
}
}

BeanFactoryPostProcessor调用链

AbstractApplicationContext#refresh() ===> AbstractApplicationContext#invokeBeanFactoryPostProcessors() ===> PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors() ===> PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors() ===> BeanFactoryPostProcessor#postProcessBeanFactory()

InitializingBean、DisposableBean

Spring 开放了扩展接口,允许自定义 bean 的初始化和销毁方法。即当 Spring 容器在 bean 进行到相应的生命周期阶段时,会自动调用我们自定义的初始化和销毁方法。这两个扩展接口即是 InitializingBeanDisposableBean

InitializingBean

1
2
3
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}

InitializingBean与SmartInitialzingSingleton的区别

  1. SmartInitialzing只作用于单例Bean,InitialzingBean无此要求;

  2. 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
      36
      protected void invokeInitMethods(String beanName, Object bean, @Nullable 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
      @Override
      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
    3
    public 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
    15
    protected void destroyBean(String beanName, @Nullable 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
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
//按接口获取spring.fatories文件中的实现类的实例
public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
Assert.notNull(factoryType, "'factoryType' must not be null");
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
List<String> factoryImplementationNames = loadFactoryNames(factoryType, classLoaderToUse);
if (logger.isTraceEnabled()) {
logger.trace("Loaded [" + factoryType.getName() + "] names: " + factoryImplementationNames);
}
List<T> result = new ArrayList<>(factoryImplementationNames.size());
for (String factoryImplementationName : factoryImplementationNames) {
result.add(instantiateFactory(factoryImplementationName, factoryType, classLoaderToUse));
}
AnnotationAwareOrderComparator.sort(result);
return result;
}

//按接口获取spring.factories文件中的实现类全称
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}

调用链路:
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
2
3
4
5
6
7
8
9
10
public class DatabaseEnvironmentPostProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
if (environment.getPropertySources().contains("databasePropertySources")) {
return;
}
...
}
}

spring.factories:

1
2
org.springframework.boot.env.EnvironmentPostProcessor=\
com.web.env.DatabaseEnvironmentPostProcessor

参考:https://juejin.cn/post/7113166186849763358

请作者喝瓶肥宅快乐水