Spring IoC

Spring IoC(Inversion of Control,控制反转)是Spring框架的核心概念之一,它是一种设计模式,用于解耦组件之间的依赖关系,提供更灵活、可维护和可测试的代码。IoC的主要思想是,将对象的创建和依赖关系的管理交给容器来处理,而不是由对象自身来创建和管理依赖

IoC(Inversion of Control)控制反转:所谓控制反转,就是把原先我们代码里面需要实现的对象创建、依赖的代码,反转给容器来帮忙实现。那么必然我们需要创建一个容器,同时需要一种描述来让容器知道需要创建的对象与对象的关系。这个描述最具体的表现就是我们看到的配置文件,或者是注解

DI(Dependency Injection)依赖注入:就是指对象被动接受依赖类而不是自己主动去找,换句话说就是指对象不是从容器中查找它依赖的类了,而是在容器实例化对象的时候主动将它依赖的类注入给它

在传统的编程中,一个对象通常负责创建其依赖的其他对象,这导致了高度耦合的代码,难以修改和维护。通过使用IoC,我们将控制权转移到框架(或容器)中,框架负责创建和管理对象的实例,并将它们注入到需要它们的组件中

Spring IoC的主要组件是Bean容器,它负责实例化、配置和管理Bean(对象)。Bean 是Spring框架中的核心组件,它们是由Spring容器创建和管理的普通Java对象。

Spring IoC的实现方式有两种:基于XML配置和基于注解配置

Spring容器启动

最基本的启动 Spring 容器的例子:

1
2
3
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationfile.xml");
}

ApplicationContext context = new ClassPathXmlApplicationContext(...) 从名字上就可以看出来,就是在 ClassPath 中寻找 xml 配置文件,根据 xml 文件内容来构建 ApplicationContext。当然,除了 ClassPathXmlApplicationContext 以外,我们也还有其他构建 ApplicationContext 的方案可供选择

ApplicationContext的继承结构

ClassPathXmlApplicationContext 的构造函数:

1
2
3
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}

实际调用的构造函数:

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

// 父类构造方法
super(parent);
// 设置Bean配置信息的路径
setConfigLocations(configLocations);
if (refresh) {
// 主要逻辑
refresh();
}
}

还有像 AnnotationConfigApplicationContextFileSystemXmlApplicationContextXmlWebApplicationContext 等都继承自父容器 AbstractApplicationContext 主要用到了装饰器模式和策略模式,最终都是调用 refresh() 方法

AbstractApplicationContext#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
82
83
84
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

// Prepare this context for refreshing.
// 1、调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
prepareRefresh();

// Tell the subclass to refresh the internal bean factory.
// 2、告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从子类的refreshBeanFactory()方法启动
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.
// 3、为BeanFactory配置容器特性,例如类加载器、事件处理器等
prepareBeanFactory(beanFactory);

try {
// Allows post-processing of the bean factory in context subclasses.
// 4、为容器的某些子类指定特殊的BeanPost事件处理器
postProcessBeanFactory(beanFactory);

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

// Register bean processors that intercept bean creation.
// 6、为BeanFactory注册BeanPost事件处理器. BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();

// Initialize message source for this context.
// 7、初始化信息源,和国际化相关.
initMessageSource();

// Initialize event multicaster for this context.
// 8、初始化容器事件传播器.
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
// 9、空方法,留给子类扩展
onRefresh();

// Check for listener beans and register them.
// 10、为事件传播器注册事件监听器.
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
// 11、初始化所有剩余的单例Bean
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
// 12、初始化容器的生命周期事件处理器,并发布容器的生命周期事件
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.
// 13、销毁已创建的Bean
destroyBeans();

// Reset 'active' flag.
// 14、取消refresh操作,重置容器的同步标识
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...
// 15、重设公共缓存
resetCommonCaches();
contextRefresh.end();
}
}
}

refresh()方法是在应用程序上下文(ApplicationContext)启动过程中的一个重要方法。它的主要作用是刷新应用程序上下文,也就是启动Spring容器并完成初始化过程,使得容器准备好处理请求和提供Bean实例。它在以下情况下被调用:

  1. Spring容器启动时,refresh()方法会在容器初始化时调用,用于创建和初始化所有注册的Bean。
  2. 在热加载(hot reloading)场景中,当类文件或配置文件发生变化时,可以手动调用refresh()方法来重新加载 ApplicationContext,实现动态更新应用程序上下文。

refresh()方法的执行过程包括以下主要步骤:

  1. 调用prepareRefresh()方法:在刷新之前执行的预处理,通常用于初始化容器的状态
  2. 调用obtainFreshBeanFactory()方法:创建或获取一个新的BeanFactory实例,这是整个IOC容器的核心。它负责Bean的注册、依赖注入等工作
  3. 调用prepareBeanFactory(beanFactory)方法:对BeanFactory进行一些设置,如注册后置处理器、添加属性编辑器等
  4. 调用postProcessBeanFactory(beanFactory)方法:允许子类在标准初始化后对BeanFactory进行进一步的定制
  5. 调用invokeBeanFactoryPostProcessors(beanFactory)方法:调用所有注册的BeanFactory后置处理器,这些后置处理器可以修改或添加BeanFactory中的Bean定义
  6. 调用registerBeanPostProcessors(beanFactory)方法:注册所有的Bean后置处理器,这些后置处理器会在Bean的初始化过程中添加额外的逻辑
  7. 调用initMessageSource()方法:初始化消息资源,用于国际化支持
  8. 调用initApplicationEventMulticaster()方法:初始化事件广播器,用于处理应用程序事件
  9. 调用onRefresh()方法:在刷新过程中的回调方法,允许子类执行自定义的刷新逻辑
  10. 调用registerListeners()方法:注册应用程序事件监听器
  11. 调用finishBeanFactoryInitialization(beanFactory)方法:完成剩余的Bean初始化工作,包括实例化非懒加载的单例Bean
  12. 调用finishRefresh()方法:在刷新过程完成后执行的回调方法
  13. 完成刷新过程,容器准备好接收请求并提供Bean实例

refresh() 方法里反复提到了一个类:BeanFactory,下面先解释一下 BeanFactory 是什么

BeanFactory

BeanFactory,从名字上也很好理解,生产 bean 的工厂,它负责生产和管理各个 bean 实例。BeanFactory 在 Spring 中是一个核心接口,它是IOC容器的基础,负责创建、管理和查找Bean对象。BeanFactory定义了访问Spring容器中Bean的标准方法,提供了IOC容器的基本功能

BeanFactory继承关系

  1. ApplicationContext 继承了 ListableBeanFactory,这个 Listable 的意思就是,通过这个接口可以获取多个 Bean
  2. ApplicationContext 继承了 HierarchicalBeanFactoryHierarchical 单词本身已经能说明问题了,也就是说我们可以在应用中起多个 BeanFactory,然后可以将各个 BeanFactory 设置为父子关系
  3. AutowireCapableBeanFactory 这个名字中的 Autowire 表明它就是用来自动装配 Bean 用的,虽然ApplicationContext 并没有继承它,但是可以通过组合的方法:ApplicationContext 接口定义中的最后一个方法 getAutowireCapableBeanFactory()
  4. ConfigurableListableBeanFactory 也是一个特殊的接口,在于它继承了第二层所有的三个接口,而 ApplicationContext 没有

refresh()

再回头来说 refresh()方法,从上到下依次:

prepareRefresh()

创建 Bean 容器前的准备工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
protected void prepareRefresh() {
// 记录启动时间,将 active 属性设置为 true,closed 属性设置为 false,它们都是 AtomicBoolean 类型
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);

... // 省略 log 配置

// 校验 xml 配置文件
getEnvironment().validateRequiredProperties();

... // 初始化部分 eventListener 容器
}

obtainFreshBeanFactory()

初始化 BeanFactory,加载 Bean、注册 Bean:

1
2
3
4
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}

AbstractRefreshableApplicationContext#refreshBeanFactory

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
protected final void refreshBeanFactory() throws BeansException {
// 如果 ApplicationContext 中已经加载过 BeanFactory 了,销毁所有 Bean,关闭 BeanFactory
// 注意,应用中 BeanFactory 本来就是可以多个的,这里可不是说应用全局是否有 BeanFactory,而是当前
// ApplicationContext 是否有 BeanFactory
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 初始化一个 DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 设置SerializationId,用于 BeanFactory 的序列化
beanFactory.setSerializationId(getId());
// 设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用
customizeBeanFactory(beanFactory);
// 加载 Bean 到 BeanFactory 中
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}

这里创建了一个 DefaultListableBeanFactory 实例,从之前的图上看得出,DefaultListableBeanFactory 实现了 ListableBeanFactoryHierarchicalBeanFactoryAutowireCapableBeanFactory,是功能最全面的 beanFactory

beanFactory 说了那么久,他是个 bean 的容器,那么 bean 是什么?bean 在代码层面上可以认为是 beanDefinition 的实例。beanDefinition 中保存了 bean 的信息

beanDefinition 的接口定义:
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
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

// 默认提供 sington 和 prototype 两种,
// 还有很多其他的比如request, session, globalSession, application, websocket他们都是基于web的扩展
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,这里涉及到 bean 继承
void setParentName(String parentName);

// 获取父 Bean
String getParentName();

// 设置 Bean 的类名称,用来通过反射来生成实例
void setBeanClassName(String beanClassName);

// 获取 Bean 的类名称
String getBeanClassName();

// 设置是否懒加载
void setLazyInit(boolean lazyInit);

boolean isLazyInit();

// 设置该 Bean 依赖的所有的 Bean,注意这里的依赖不是指属性依赖(如 @Autowire 标记的),
// 是 depends-on="" 属性设置的值。
void setDependsOn(String... dependsOn);

// 返回该 Bean 的所有依赖
String[] getDependsOn();

// 设置该 Bean 是否可以注入到其他 Bean 中,只对根据类型注入有效,
// 如果根据名称注入,即使这边设置了 false,也是可以的
void setAutowireCandidate(boolean autowireCandidate);

// setPrimary。同一接口的多个实现,如果不指定名字的话,Spring 会优先选择设置 primary 为 true 的 bean
void setPrimary(boolean primary);

// 如果该 Bean 采用工厂方法生成,指定工厂名称
void setFactoryBeanName(String factoryBeanName);
// 获取工厂名称
String getFactoryBeanName();
// 指定工厂类中的 工厂方法名称
void setFactoryMethodName(String factoryMethodName);
// 获取工厂类中的 工厂方法名称
String getFactoryMethodName();

// 构造器参数
ConstructorArgumentValues getConstructorArgumentValues();

// Bean 中的属性值,后面给 bean 注入属性值的时候会说到
MutablePropertyValues getPropertyValues();

// 是否 singleton
boolean isSingleton();

// 是否 prototype
boolean isPrototype();

// 如果这个 Bean 是被设置为 abstract,那么不能实例化,
boolean isAbstract();

int getRole();
String getDescription();
String getResourceDescription();
BeanDefinition getOriginatingBeanDefinition();
}
customizeBeanFactory(beanFactory)
1
2
3
4
5
6
7
8
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}

配置是否允许 beanDefinition 覆盖、是否允许循环引用

loadBeanDefinitions(beanFactory)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 给这个 BeanFactory 实例化一个 XmlBeanDefinitionReader
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));


// 初始化 BeanDefinitionReader,其实这个是提供给子类覆写的,
initBeanDefinitionReader(beanDefinitionReader);
// 加载/注册 BeanDefinitions
loadBeanDefinitions(beanDefinitionReader);
}

prepareBeanFactory(beanFactory)

把在 xml 配置的 bean 都注册以后,会”手动”注册一些特殊的 bean。

这里简单介绍下 prepareBeanFactory(factory) 方法:

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
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置 BeanFactory 的类加载器,我们知道 BeanFactory 需要加载类,也就需要类加载器,
// 这里设置为加载当前 ApplicationContext 类的类加载器
beanFactory.setBeanClassLoader(getClassLoader());
if (!shouldIgnoreSpel) {
// 设置 BeanExpressionResolver
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

// 添加一个 BeanPostProcessor,这个 processor 比较简单:
// 实现了 Aware 接口的 beans 在初始化的时候,这个 processor 负责回调,
// 这个我们很常用,如我们会为了获取 ApplicationContext 而 implement ApplicationContextAware
// 注意:它不仅仅回调 ApplicationContextAware,还会负责回调 EnvironmentAware、ResourceLoaderAware 等,看下源码就清楚了
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);

// 下面几行的意思就是,如果某个 bean 依赖于以下几个接口的实现类,在自动装配的时候忽略它们,
// Spring 会通过其他方式来处理这些依赖。
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

... // 省略

// 注册默认的 Environment Bean
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}

finishBeanFactoryInitialization(beanFactory)

负责初始化所有的 singleton beans。到目前为止,应该说 BeanFactory 已经创建完成,并且所有的实现了 BeanFactoryPostProcessor 接口的 Bean 都已经初始化并且其中的 postProcessBeanFactory(factory) 方法已经得到回调执行了。而且 Spring 已经“手动”注册了一些特殊的 Bean,如 environmentsystemProperties

剩下的就是初始化 singleton beans 了,我们知道它们是单例的,如果没有设置懒加载,那么 Spring 会在接下来初始化所有的 singleton beans

1
2
3
4
5
6
7
8
9
10
11
12
13
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 首先,初始化名字为 conversionService 的 Bean
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}

... // 略过

// 开始初始化
beanFactory.preInstantiateSingletons();
}

preInstantiateSingletons()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}

// this.beanDefinitionNames 保存了所有的 beanNames
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

// 下面这个循环,触发所有的非懒加载的 singleton beans 的初始化操作
for (String beanName : beanNames) {
... // 略过
// 对于普通的 bean,通过这个方法初始化
getBean(beanName);
... // 略过
}
}

getBean()

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
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}

protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 获取一个 “正统的” beanName,处理两种情况,一个是前面说的 FactoryBean(前面带 ‘&’),
// 一个是别名问题,因为这个方法是 getBean,获取 Bean 用的,你要是传一个别名进来,是完全可以的
final String beanName = transformedBeanName(name);

// 返回值
Object bean;

// 检查下是不是已经创建过了
Object sharedInstance = getSingleton(beanName);

// 这里说下 args 呗,虽然看上去一点不重要。前面我们一路进来的时候都是 getBean(beanName),
// 所以 args 传参其实是 null 的,但是如果 args 不为空的时候,那么意味着调用方不是希望获取 Bean,而是创建 Bean
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("...");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 下面这个方法:如果是普通 Bean 的话,直接返回 sharedInstance,
// 如果是 FactoryBean 的话,返回它创建的那个实例对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else {
if (isPrototypeCurrentlyInCreation(beanName)) {
// 创建过了此 beanName 的 prototype 类型的 bean,那么抛异常,
// 往往是因为陷入了循环引用
throw new BeanCurrentlyInCreationException(beanName);
}

// 检查一下这个 BeanDefinition 在容器中是否存在
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 如果当前容器不存在这个 BeanDefinition,试试父容器中有没有
String nameToLookup = originalBeanName(name);
if (args != null) {
// 返回父容器的查询结果
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}

if (!typeCheckOnly) {
// typeCheckOnly 为 false,将当前 beanName 放入一个 alreadyCreated 的 Set 集合中。
markBeanAsCreated(beanName);
}

/*
* 准备创建 Bean,对于 singleton 的 Bean 来说,容器中还没创建过此 Bean;
* 对于 prototype 的 Bean 来说,创建一个新的 Bean。
*/
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

// 先初始化依赖的所有 Bean,这个很好理解。
// 注意,这里的依赖指的是 depends-on 中定义的依赖
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 检查是不是有循环依赖,这里的循环依赖和我们前面说的循环依赖又不一样,这里肯定是不允许出现的,不然要乱套了,读者想一下就知道了
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注册一下依赖关系
registerDependentBean(dep, beanName);
// 先初始化被依赖项
getBean(dep);
}
}

// 如果是 singleton scope 的,创建 singleton 的实例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
// 执行创建 Bean
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

// 如果是 prototype scope 的,创建 prototype 的实例
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
// 执行创建 Bean
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

// 如果不是 singleton 和 prototype 的话,需要委托给相应的实现类来处理
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
// 执行创建 Bean
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}

// 最后,检查一下类型对不对,不对的话就抛异常,对的话就返回了
if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}

然后是createBean()

AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])

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
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;

// 确保 BeanDefinition 中的 Class 被加载
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}

// 准备方法覆写
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}

try {
// 让 InstantiationAwareBeanPostProcessor 在这一步有机会返回代理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
// 创建 bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}

AbstractAutowireCapableBeanFactory#doCreateBean

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
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {

// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 说明不是 FactoryBean,这里实例化 Bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
... // 跳过

// 解决循环依赖的问题
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 向容器注册一个单例Bean实例的工厂
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

// Initialize the bean instance.
Object exposedObject = bean;
try {
// 负责属性装配,因为前面的实例只是实例化了,并没有设值
populateBean(beanName, mbd, instanceWrapper);
// 处理 bean 初始化完成后的各种回调(例init-method,InitializingBean,BeanPostProcessor)
exposedObject = initializeBean(beanName, exposedObject, mbd);
}

... // 省略
return exposedObject;
}

基于Annotation的IoC初始化

Annotation

从Spring2.0以后的版本中,Spring也引入了基于注解(Annotation)方式的配置,注解(Annotation)是JDK1.5中引入的一个新特性,用于简化Bean的配置,可以取代XML配置文件。开发人员对注解(Annotation)的态度也是萝卜白菜各有所爱,个人认为注解可以简化配置,提高开发速度,但也给后期维护增加了难度。随着Spring Boot的兴起,基于注解的开发甚至实现了零配置。Spring IOC容器对于类级别的注解和类内部的注解分一下两种处理策略:

  1. 类级别的注解:@Component@Repository@Controller@Service以及JavaEE6的@ManagedBean@Named注解,都是添加在类上面的类级别注解,Spring容器根据注解的过滤规则扫描读取注解Bean定义类,并将其注册到Spring IOC容器中。
  2. 类内部的注解:@Autowire@Value@Resource以及EJB和WebService相关的注解等,都是添加在类内部的字段或者方法上的类内部注解,Spring IOC容器通过Bean后置注解处理器解析Bean内部的注解。

定位Bean扫描路径

在Spring中管理注解Bean定义的容器有两个:AnnotationConfigApplicationContextAnnotationConfigWebApplicationContext。这两个类的专门处理Spring注解方式配置的容器,直接依赖于注解作为容器配置信息来源的IOC容器。AnnotationConfigWebApplicationContextAnnotationConfigApplicationContext 的Web版本,两者的用法以及对注解的处理方式几乎没有差别。现在我们以 AnnotationConfigApplicationContext 为例看它的源码:

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
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {

//保存一个读取注解的Bean定义读取器,并将其设置到容器中
private final AnnotatedBeanDefinitionReader reader;

//保存一个扫描指定类路径中注解Bean定义的扫描器,并将其设置到容器中
private final ClassPathBeanDefinitionScanner scanner;

//默认构造函数,初始化一个空容器,容器不包含任何 Bean 信息,需要在稍后通过调用其register()
//方法注册配置类,并调用refresh()方法刷新容器,触发容器对注解Bean的载入、解析和注册过程
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}

public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
super(beanFactory);
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}

//最常用的构造函数,通过将涉及到的配置类传递给该构造函数,以实现将相应配置类中的Bean自动注册到容器中
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}

//该构造函数会自动扫描以给定的包及其子包下的所有类,并自动识别所有的Spring Bean,将其注册到容器中
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages);
refresh();
}

@Override
public void setEnvironment(ConfigurableEnvironment environment) {
super.setEnvironment(environment);
this.reader.setEnvironment(environment);
this.scanner.setEnvironment(environment);
}

//为容器的注解Bean读取器和注解Bean扫描器设置Bean名称产生器
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
this.reader.setBeanNameGenerator(beanNameGenerator);
this.scanner.setBeanNameGenerator(beanNameGenerator);
getBeanFactory().registerSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
}

//为容器的注解Bean读取器和注解Bean扫描器设置作用范围元信息解析器
public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
this.reader.setScopeMetadataResolver(scopeMetadataResolver);
this.scanner.setScopeMetadataResolver(scopeMetadataResolver);
}

//为容器注册一个要被处理的注解Bean,新注册的Bean,必须手动调用容器的
//refresh()方法刷新容器,触发容器对新注册的Bean的处理
public void register(Class<?>... annotatedClasses) {
Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
this.reader.register(annotatedClasses);
}

//扫描指定包路径及其子包下的注解类,为了使新添加的类被处理,必须手动调用
//refresh()方法刷新容器
public void scan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
this.scanner.scan(basePackages);
}

public <T> void registerBean(Class<T> annotatedClass, Object... constructorArguments) {
registerBean(null, annotatedClass, constructorArguments);
}

public <T> void registerBean(@Nullable String beanName, Class<T> annotatedClass, Object... constructorArguments) {
this.reader.doRegisterBean(annotatedClass, null, beanName, null,
bd -> {
for (Object arg : constructorArguments) {
bd.getConstructorArgumentValues().addGenericArgumentValue(arg);
}
});
}

@Override
public <T> void registerBean(@Nullable String beanName, Class<T> beanClass, @Nullable Supplier<T> supplier,
BeanDefinitionCustomizer... customizers) {

this.reader.doRegisterBean(beanClass, supplier, beanName, null, customizers);
}

}

通过上面的源码分析,我们可以看到Spring对注解的处理分为两种方式:

  1. 直接将注解Bean注册到容器中。可以在初始化容器时注册,也可以在容器创建之后手动调用注册方法向容器注册,然后通过手动刷新容器,使得容器对注册的注解Bean进行处理
  2. 通过扫描指定的包及其子包下的所有类。在初始化注解容器时指定要自动扫描的路径,如果容器创建以后向给定路径动态添加注解Bean,则需要手动调用容器扫描方法,然后手动刷新容器,使得容器对锁注册的Bean进行处理

接下来,将会对两种处理方式详细分析其实现过程

读取Annotation元数据

直接将注解Bean注册到容器中

AnnotationConfigApplicationContext 通过调用注解Bean定义读取器

AnnotatedBeanDefinitionReaderregister() 方法向容器注册指定注解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
//注册多个注解Bean定义类
public void register(Class<?>... annotatedClasses) {
for (Class<?> annotatedClass : annotatedClasses) {
registerBean(annotatedClass);
}
}

//注册一个注解Bean定义类
public void registerBean(Class<?> annotatedClass) {
doRegisterBean(annotatedClass, null, null, null);
}

public <T> void registerBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier) {
doRegisterBean(annotatedClass, instanceSupplier, null, null);
}

public <T> void registerBean(Class<T> annotatedClass, String name, @Nullable Supplier<T> instanceSupplier) {
doRegisterBean(annotatedClass, instanceSupplier, name, null);
}

//Bean定义读取器注册注解Bean定义的入口方法
@SuppressWarnings("unchecked")
public void registerBean(Class<?> annotatedClass, Class<? extends Annotation>... qualifiers) {
doRegisterBean(annotatedClass, null, null, qualifiers);
}

//Bean定义读取器向容器注册注解Bean定义类
@SuppressWarnings("unchecked")
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
doRegisterBean(annotatedClass, null, name, qualifiers);
}

//Bean定义读取器向容器注册注解Bean定义类
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

//根据指定的注解Bean定义类,创建Spring容器中对注解Bean的封装的数据结构
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}

abd.setInstanceSupplier(instanceSupplier);
//解析注解Bean定义的作用域,若@Scope("prototype"),则Bean为原型类型;
//若@Scope("singleton"),则Bean为单态类型
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
//为注解Bean定义设置作用域
abd.setScope(scopeMetadata.getScopeName());
//为注解Bean定义生成Bean名称
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

//处理注解Bean定义中的通用注解
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
//如果在向容器注册注解Bean定义时,使用了额外的限定符注解,则解析限定符注解。
//主要是配置的关于autowiring自动依赖注入装配的限定条件,即@Qualifier注解
//Spring自动依赖注入装配默认是按类型装配,如果使用@Qualifier则按名称
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
//如果配置了@Primary注解,设置该Bean为autowiring自动依赖注入装//配时的首选
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
//如果配置了@Lazy注解,则设置该Bean为非延迟初始化,如果没有配置,
//则该Bean为预实例化
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
//如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一
//个autowiring自动依赖注入装配限定符,该Bean在进autowiring
//自动依赖注入装配时,根据名称装配限定符指定的Bean
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}

//创建一个指定Bean名称的Bean定义对象,封装注解Bean定义类数据
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
//根据注解Bean定义类中配置的作用域,创建相应的代理对象
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//向IOC容器注册注解Bean类定义对象
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

通过上面的源码分析,我们可以看到注册注解Bean定义类的基本步骤:

  1. 需要使用注解元数据解析器计息注解Bean中关于作用域的配置。
  2. 使用AnnotationConfigUtilsprocessCommonDefinitionAnnotations()方法处理注解Bean定义类中通用注解。
  3. 使用AnnotationConfigUtilsappliyScopedProxyMode()方法创建对于作用域的代理对象。
  4. 通过BeanDefinitaionReaderUtils向容器注册Bean。

AnnotationScopeMetadataResolver解析作用域元数据

AnnotationScopeMetadataResolver 通过 resolveScopeMetadata() 方法解析注册Bean定义类的作用域元信息,即判断注册的Bean是原型类型(prototype)还是单例类型(singleton),其源码如下:

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
//解析注解Bean定义类中的作用域元信息
@Override
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
ScopeMetadata metadata = new ScopeMetadata();
if (definition instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
//从注解Bean定义类的属性中查找属性为”Scope”的值,即@Scope注解的值
//annDef.getMetadata().getAnnotationAttributes()方法将Bean
//中所有的注解和注解的值存放在一个map集合中
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
annDef.getMetadata(), this.scopeAnnotationType);
//将获取到的@Scope注解的值设置到要返回的对象中
if (attributes != null) {
metadata.setScopeName(attributes.getString("value"));
//获取@Scope注解中的proxyMode属性值,在创建代理对象时会用到
ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
//如果@Scope的proxyMode属性为DEFAULT或者NO
if (proxyMode == ScopedProxyMode.DEFAULT) {
//设置proxyMode为NO
proxyMode = this.defaultProxyMode;
}
//为返回的元数据设置proxyMode
metadata.setScopedProxyMode(proxyMode);
}
}
//返回解析的作用域元信息对象
return metadata;
}

上述代码中:AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor( annDef.getMetadata(), this.scopeAnnotationType); 这里就是获取对象中指定类型的注解值。

AnnotationConfigUtils处理注解Bean定义类中的通用注解

AnnotationConfigUtils 类的 processCommonDefinitionAnnotations() 在向容器注册Bean之前,首先对注解Bean定义类中的通用Spring注解进行处理,源码如下:

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
public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
processCommonDefinitionAnnotations(abd, abd.getMetadata());
}

//处理Bean定义中通用注解
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
//如果Bean定义中有@Lazy注解,则将该Bean预实例化属性设置为@lazy注解的值
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}

else if (abd.getMetadata() != metadata) {
lazy = attributesFor(abd.getMetadata(), Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
}
//如果Bean定义中有@Primary注解,则为该Bean设置为autowiring自动依赖注入装配的首选对象
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
//如果Bean定义中有@ DependsOn注解,则为该Bean设置所依赖的Bean名称,
//容器将确保在实例化该Bean之前首先实例化所依赖的Bean
AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
if (dependsOn != null) {
abd.setDependsOn(dependsOn.getStringArray("value"));
}

if (abd instanceof AbstractBeanDefinition) {
AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
AnnotationAttributes role = attributesFor(metadata, Role.class);
if (role != null) {
absBd.setRole(role.getNumber("value").intValue());
}
AnnotationAttributes description = attributesFor(metadata, Description.class);
if (description != null) {
absBd.setDescription(description.getString("value"));
}
}
}

AnnotationConfigUtils根据注解Bean定义类中配置的作用域为其应用响应的代理策略

AnnotationConfigUtils 类的 applyScopedProxyMode() 方法根据注解Bean定义类中配置的作用域@Scope注解的值,为Bean定义应用响应的代理模式,主要是在Spring面向切面编程(AOP)中使用。

源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//根据作用域为Bean应用引用的代码模式
static BeanDefinitionHolder applyScopedProxyMode(
ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {

//获取注解Bean定义类中@Scope注解的proxyMode属性值
ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
//如果配置的@Scope注解的proxyMode属性值为NO,则不应用代理模式
if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
return definition;
}
//获取配置的@Scope注解的proxyMode属性值,如果为TARGET_CLASS
//则返回true,如果为INTERFACES,则返回false
boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
//为注册的Bean创建相应模式的代理对象
return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}

这段为Bean引用创建相应模式的代理。这里不做深入分析。

BeanDefinitionReaderUtils 向容器注册Bean

BeanDefinitionReaderUtils主要是校验BeanDefinition信息,然后将Bean添加到容器中一个管理BeanDefinition的HashMap中。

扫描指定包并解析为BeanDefinition

当创建注解处理器时,如果传入的初始参数是注解Bean定义类锁在的包时,注解容器将扫描给定的包及其子包,将扫描到的注解Bean定义载入并注册。

ClassPathBeanDefinitionScanner扫描给定的包及其子包

AnnotationConfigApplicationContext通过调用类路径Bean定义扫描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
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
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {

private final BeanDefinitionRegistry registry;

private BeanDefinitionDefaults beanDefinitionDefaults = new BeanDefinitionDefaults();

@Nullable
private String[] autowireCandidatePatterns;

private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();

private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();

private boolean includeAnnotationConfig = true;

//创建一个类路径Bean定义扫描器
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
this(registry, true);
}

//为容器创建一个类路径Bean定义扫描器,并指定是否使用默认的扫描过滤规则。
//即Spring默认扫描配置:@Component、@Repository、@Service、@Controller
//注解的Bean,同时也支持JavaEE6的@ManagedBean和JSR-330的@Named注解
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment) {

this(registry, useDefaultFilters, environment,
(registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
}

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {

Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//为容器设置加载Bean定义的注册器
this.registry = registry;

if (useDefaultFilters) {
registerDefaultFilters();
}
setEnvironment(environment);
//为容器设置资源加载器
setResourceLoader(resourceLoader);
}

@Override
public final BeanDefinitionRegistry getRegistry() {
return this.registry;
}

public void setBeanDefinitionDefaults(@Nullable BeanDefinitionDefaults beanDefinitionDefaults) {
this.beanDefinitionDefaults =
(beanDefinitionDefaults != null ? beanDefinitionDefaults : new BeanDefinitionDefaults());
}

public BeanDefinitionDefaults getBeanDefinitionDefaults() {
return this.beanDefinitionDefaults;
}

public void setAutowireCandidatePatterns(@Nullable String... autowireCandidatePatterns) {
this.autowireCandidatePatterns = autowireCandidatePatterns;
}

public void setBeanNameGenerator(@Nullable BeanNameGenerator beanNameGenerator) {
this.beanNameGenerator = (beanNameGenerator != null ? beanNameGenerator : new AnnotationBeanNameGenerator());
}

public void setScopeMetadataResolver(@Nullable ScopeMetadataResolver scopeMetadataResolver) {
this.scopeMetadataResolver =
(scopeMetadataResolver != null ? scopeMetadataResolver : new AnnotationScopeMetadataResolver());
}

public void setScopedProxyMode(ScopedProxyMode scopedProxyMode) {
this.scopeMetadataResolver = new AnnotationScopeMetadataResolver(scopedProxyMode);
}

public void setIncludeAnnotationConfig(boolean includeAnnotationConfig) {
this.includeAnnotationConfig = includeAnnotationConfig;
}

//调用类路径Bean定义扫描器入口方法
public int scan(String... basePackages) {
//获取容器中已经注册的Bean个数
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();

//启动扫描器扫描给定包
doScan(basePackages);

// Register annotation config processors, if necessary.
//注册注解配置(Annotation config)处理器
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

//返回注册的Bean个数
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}

//类路径Bean定义扫描器扫描给定包及其子包
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
//创建一个集合,存放扫描到Bean定义的封装类
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
//遍历扫描所有给定的包
for (String basePackage : basePackages) {
//调用父类ClassPathScanningCandidateComponentProvider的方法
//扫描给定类路径,获取符合条件的Bean定义
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
//遍历扫描到的Bean
for (BeanDefinition candidate : candidates) {
//获取Bean定义类中@Scope注解的值,即获取Bean的作用域
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
//为Bean设置注解配置的作用域
candidate.setScope(scopeMetadata.getScopeName());
//为Bean生成名称
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
//如果扫描到的Bean不是Spring的注解Bean,则为Bean设置默认值,
//设置Bean的自动依赖注入装配属性等
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
//如果扫描到的Bean是Spring的注解Bean,则处理其通用的Spring注解
if (candidate instanceof AnnotatedBeanDefinition) {
//处理注解Bean中通用的注解,在分析注解Bean定义类读取器时已经分析过
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
//根据Bean名称检查指定的Bean是否需要在容器中注册,或者在容器中冲突
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
//根据注解中配置的作用域,为Bean应用相应的代理模式
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
//向容器注册扫描到的Bean
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}

...

}

类路径Bean定义扫描器ClassPathBeanDefinitionScanner主要通过findCandidateComponents()方法调用其父类ClassPathScanningCandidateComponentProvider类来扫描获取给定包及其子包下的类。

ClassPathScanningCandidateComponentProvider扫描给定包及其子包的类

ClassPathScanningCandidateComponentProvider 类的 findCandidateComponents() 方法具体实现扫描给定类路径包的功能,主要源码如下:

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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {

static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";


protected final Log logger = LogFactory.getLog(getClass());

private String resourcePattern = DEFAULT_RESOURCE_PATTERN;

//保存过滤规则要包含的注解,即Spring默认的@Component、@Repository、@Service、
//@Controller注解的Bean,以及JavaEE6的@ManagedBean和JSR-330的@Named注解
private final List<TypeFilter> includeFilters = new LinkedList<>();

//保存过滤规则要排除的注解
private final List<TypeFilter> excludeFilters = new LinkedList<>();

...

//构造方法,该方法在子类ClassPathBeanDefinitionScanner的构造方法中被调用
public ClassPathScanningCandidateComponentProvider(boolean useDefaultFilters) {
this(useDefaultFilters, new StandardEnvironment());
}


public ClassPathScanningCandidateComponentProvider(boolean useDefaultFilters, Environment environment) {
//如果使用Spring默认的过滤规则,则向容器注册过滤规则
if (useDefaultFilters) {
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(null);
}

.....

//向容器注册过滤规则
@SuppressWarnings("unchecked")
protected void registerDefaultFilters() {
//向要包含的过滤规则中添加@Component注解类,注意Spring中@Repository
//@Service和@Controller都是Component,因为这些注解都添加了@Component注解
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
//获取当前类的类加载器
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
//向要包含的过滤规则添加JavaEE6的@ManagedBean注解
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
}
try {
//向要包含的过滤规则添加@Named注解
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}

.......

//扫描给定类路径的包
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
return scanCandidateComponents(basePackage);
}
}

.......

private Set<BeanDefinition> addCandidateComponentsFromIndex(CandidateComponentsIndex index, String basePackage) {
//创建存储扫描到的类的集合
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
Set<String> types = new HashSet<>();
for (TypeFilter filter : this.includeFilters) {
String stereotype = extractStereotype(filter);
if (stereotype == null) {
throw new IllegalArgumentException("Failed to extract stereotype from "+ filter);
}
types.addAll(index.getCandidateTypes(basePackage, stereotype));
}
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
for (String type : types) {
//为指定资源获取元数据读取器,元信息读取器通过汇编(ASM)读//取资源元信息
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(type);
//如果扫描到的类符合容器配置的过滤规则
if (isCandidateComponent(metadataReader)) {
//通过汇编(ASM)读取资源字节码中的Bean定义元信息
AnnotatedGenericBeanDefinition sbd = new AnnotatedGenericBeanDefinition(
metadataReader.getAnnotationMetadata());
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Using candidate component class from index: " + type);
}
candidates.add(sbd);
}
else {
if (debugEnabled) {
logger.debug("Ignored because not a concrete top-level class: " + type);
}
}
}
else {
if (traceEnabled) {
logger.trace("Ignored because matching an exclude filter: " + type);
}
}
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
return candidates;
}

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
for (Resource resource : resources) {
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
if (resource.isReadable()) {
try {
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
candidates.add(sbd);
}
else {
if (debugEnabled) {
logger.debug("Ignored because not a concrete top-level class: " + resource);
}
}
}
else {
if (traceEnabled) {
logger.trace("Ignored because not matching any filter: " + resource);
}
}
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to read candidate component class: " + resource, ex);
}
}
else {
if (traceEnabled) {
logger.trace("Ignored because not readable: " + resource);
}
}
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
return candidates;
}


.......

//判断元信息读取器读取的类是否符合容器定义的注解过滤规则
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
//如果读取的类的注解在排除注解过滤规则中,返回false
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return false;
}
}
//如果读取的类的注解在包含的注解的过滤规则中,则返回ture
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}
//如果读取的类的注解既不在排除规则,也不在包含规则中,则返回false
return false;
}

.......

}

注册注解BeanDefinition

AnnotationConfigWebApplicationContextAnnotationConfigApplicationContext 的 Web 版, 它们对于注解 Bean 的注册和扫描是基本相同的,但是 AnnotationConfigWebApplicationContext 对注解 Bean 定义的载入稍有不同,AnnotationConfigWebApplicationContext 注入注解 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
//载入注解Bean定义资源
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
//为容器设置注解Bean定义读取器
AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
//为容器设置类路径Bean定义扫描器
ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);

//获取容器的Bean名称生成器
BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
//为注解Bean定义读取器和类路径扫描器设置Bean名称生成器
if (beanNameGenerator != null) {
reader.setBeanNameGenerator(beanNameGenerator);
scanner.setBeanNameGenerator(beanNameGenerator);
beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
}

//获取容器的作用域元信息解析器
ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
//为注解Bean定义读取器和类路径扫描器设置作用域元信息解析器
if (scopeMetadataResolver != null) {
reader.setScopeMetadataResolver(scopeMetadataResolver);
scanner.setScopeMetadataResolver(scopeMetadataResolver);
}

if (!this.annotatedClasses.isEmpty()) {
if (logger.isInfoEnabled()) {
logger.info("Registering annotated classes: [" +
StringUtils.collectionToCommaDelimitedString(this.annotatedClasses) + "]");
}
reader.register(this.annotatedClasses.toArray(new Class<?>[this.annotatedClasses.size()]));
}

if (!this.basePackages.isEmpty()) {
if (logger.isInfoEnabled()) {
logger.info("Scanning base packages: [" +
StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
}
scanner.scan(this.basePackages.toArray(new String[this.basePackages.size()]));
}

//获取容器定义的Bean定义资源路径
String[] configLocations = getConfigLocations();
//如果定位的Bean定义资源路径不为空
if (configLocations != null) {
for (String configLocation : configLocations) {
try {
//使用当前容器的类加载器加载定位路径的字节码类文件
Class<?> clazz = ClassUtils.forName(configLocation, getClassLoader());
if (logger.isInfoEnabled()) {
logger.info("Successfully resolved class for [" + configLocation + "]");
}
reader.register(clazz);
}
catch (ClassNotFoundException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not load class for config location [" + configLocation +
"] - trying package scan. " + ex);
}
//如果容器类加载器加载定义路径的Bean定义资源失败
//则启用容器类路径扫描器扫描给定路径包及其子包中的类
int count = scanner.scan(configLocation);
if (logger.isInfoEnabled()) {
if (count == 0) {
logger.info("No annotated classes found for specified class/package [" + configLocation + "]");
}
else {
logger.info("Found " + count + " annotated classes in package [" + configLocation + "]");
}
}
}
}
}
}

以上就是解析和注入注解配置资源的全过程分析

参考:https://github.com/wenbin8/doc/blob/master/Spring/02-Spring-IOC%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90.md

IOC容器总结

现在通过上面的代码,总结一下IOC容器初始化的基本步骤:

  1. 初始化的入口在容器实现中的refresh()调用来完成。
  2. 对Bean定义载入IOC容器使用的方法是loadBeanDefinition(),其中大致过程如下:通过ResourceLoader来完成资源文件位置的定位,DefaultResourceLoader是默认实现,同时上下文本身就给出了ResourceLoader的实现,可以从类路径、文件系统、URL等方式来定位资源位置。如果是XmlBeanFactory作为IOC容器,那么需要为它指定Bean定义的资源,也就是Bean定义文件时通过Resource来把IOC容器处理,容器通过BeanDefinitionReader来完成定义信息的解析和Bean信息注册,往往使用的是XmlBeanDefinitionReader来解析Bean的XML定义文件,实际处理过程是委托给BeanDefinitionParserDelegate来完成的,从而得到bean的定义信息,这些信息在Spring中使用BeanDefinition对象来表示,这个名字可以让我们想到 loadBeanDefinition()registerBeanDefinition() 这些相关方法。它们都是为处理 BeanDefinitin 服务的,容器解析得到 BeanDefinition 以后,需要把它在 IOC 容器中注册,这由IOC实现BeanDefinitionRegistry接口来实现。注册过程就是在IOC容器内部维护的一个 HashMap来保存得到的BeanDefinition的过程。这个HashMap是IOC容器持有Bean信息的场所,以后对Bean的操作都是围绕这个HashMap来实现的。
  3. 然后通过BeanFactoryApplicationContext来享受到Spring IOC的服务了,在使用IOC容器的时候,我们注意到除了少量粘合代码,绝大多数以正确 IOC 风格编写的应用程序代码完全不用关心如何到达工厂,因为容器将把这些对象与容器管理的其他对象钩在一起。基本的策略是把工厂放到已知的地方,最好是放在对预期使用的上下文有意义的地方,以及代码将实际需要访问工厂的地方。Spring 本身提供了对声明式载入 web 应用程序用法的应用程序上下文,并将其存储在 ServletContext 中的框架 实现

Spring IoC
https://sugayoiya.github.io/posts/9827.html
作者
Sugayoiya
发布于
2021年7月25日
许可协议