1 前言

spring架构图,摘自spring官网

最底层的核心容器,即ioc容器是整个spring框架的根基。

其spring ioc容器的工作能力的简化图,摘自网页

本文重点内容:

  • 基于spring 5.2.x版本 ,spring ioc容器设计思路,及实现过程?

2 spring ioc容器

2.1 依赖反转,依赖注入,ioc容器

但凡聊spring ioc容器都说到几个概念:

  • 依赖倒置原则(DIP):一种软件架构设计的原则(抽象概念),高层模块定义接口,低层模块负责实现的设计原则。
  • 控制反转(IoC):一种反转流、依赖和接口的方式(DIP的具体实现方式),将依赖(低层模块)对象的获得交给第三方(系统)来控制,即依赖对象不在被依赖模块的类中直接通过new来获取,解耦组件(对象)之间复杂依赖关系。
  • 依赖注入(DI):IoC的一种实现方式,用来反转依赖(IoC的具体实现方式),需要依赖(低层模块)对象的引用传递给被依赖(高层模块)对象。
  • IoC容器:依赖注入的框架,用来映射依赖,管理对象创建和生存周期(DI框架)。

为什么要控制反转?
如果合作对象的引用或依赖关系的管理由具体对象来完成,会导致代码的高度耦合和测试性降低。

哪些方面的控制反转了?
依赖对象的获得被反转了

在spring中,ioc容器是实现依赖反转模式的载体,它可以在对象生成或初始化时直接将数据注入到对象中,也可以通过将对象引用注入到对象数据域中的方式来注入对方法调用的依赖。

依赖注入的实现3种方式:

  • 接口注入
  • setter注入
  • 构造器注入

2.2 spring ioc容器的设计

spring ioc容器的设计分为两条路线,

ioc容器的设计路线,BeanFactory ==> HierarchicalBeanFactory ==>ConfigurableBeanFactory
应用上下文的设计路线,BeanFactory ==> ListableBeanFactory ==> ApplicationContext ==> ConfigurableApplicationContext

摘自《spring技术内幕》

2.3 ioc容器的设计路线

设计路线,BeanFactory ==> HierarchicalBeanFactory ==>ConfigurableBeanFactory

BeanFactory接口定义了ioc容器的基本规范,提供了getBean()等基本能力。

HierarchicalBeanFactory接口在BeanFactory的基础上加了getParentBeanFactory方法,使BeanFactory具备了双亲ioc容器管理的功能。

ConfigurableBeanFactory接口提供了配置Beanfactory的各种方法,配置双亲ioc容器,addBeanPostProcessor()等方法。

ioc容器到目前为止还没有提供容器的能力,就是装Bean的能力。

2.4 应用上下文的设计路线

设计路线,BeanFactory ==> ListableBeanFactory ==> ApplicationContext ==> ConfigurableApplicationContext

应用上下文可以说是ioc容器的高级模式了。

ListableBeanFactory具备了操作BeanDefinition的能力,如获取beanDefinition数量等方法

ApplicationContext接口实现了下面6大接口:

  • EnvironmentCapable接口,提供了获取Environment方法
  • MessageSource接口,用于解析消息,支持不同的数据源,国际化等
  • ApplicationEventPublisher接口,封装了事件发布功能
  • ResourcePatternResolver接口,访问数据源,具备了从不同地方得到Bean定义资源的能力,比如:xml,java config,注解等等。
  • ListableBeanFactory接口,
  • HierarchicalBeanFactory接口,

ConfigurableApplicationContext,提供了一个重要的方法refresh()方法,最重要的是扩展了配置上下文的功能,和控制上下文生命周期的能力等等。

2.5 ioc容器的具体实现类

写个spring demo ,找出ioc容器的具体实现类。

ClassPathXmlApplicationContext的uml图中可观察到它的设计路线:

调试程序在AbstractRefreshableApplicationContext抽象类中实现了应用上下文,其中刷新上下文的refreash()方法,可知道具体实现ioc容器的是DefaultListableBeanFactory。

接下来具体看下DefaultListableBeanFactory类具体是如何实现ioc容器的?

2.5.1 作为ioc容器的基础设计路线

相比于上面的关系图,多了ConfigurableListableBeanFactory接口

ConfigurableListableBeanFactory接口主要增加了指定忽略类型和接口等

2.5.2 作为iox容器的高级(应用上下文)设计路线

看类关系还是挺复杂的,AliasRegistry接口主要提供了管理别称的能力。

主要有如下路线:

1, BeanFactory ==> AutowireCapableBeanFactory ==> AbstractAutowireCapableBeanFactory ==> DefaultListableBeanFactory

这条路线中AutowireCapableBeanFactory定义了自动注入bean,创建bean,初始化bean等方法,而真正实现这些方法的类是AbstractAutowireCapableBeanFactory

2, SingletonBeanRegistry ==> DefaultSingletonBeanRegistry ==> FactoryBeanRegistrySupport ==> AbstractBeanFactory ==> AutowireCapableBeanFactory ==> DefaultListableBeanFactory

这条路线中最重要的是SingletonBeanRegistry接口,这个接口提供了单列bean的注册,删除,获取BeanDefinition的方法。当然这只是个接口,这些方法的具体实现在DefaultListableBeanFactory中。

2.5.3 DefaultListableBeanFactory类的设计与实现

DefaultListableBeanFactory类让ioc容器拥有作为“容器”的能力,可以装载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
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

@Nullable
private static Class<?> javaxInjectProviderClass;

static {
try {
javaxInjectProviderClass =
ClassUtils.forName("javax.inject.Provider", DefaultListableBeanFactory.class.getClassLoader());
} catch (ClassNotFoundException ex) {
// JSR-330 API not available - Provider interface simply not supported then.
javaxInjectProviderClass = null;
}
}


/**
* Map from serialized id to factory instance.
*/
private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
new ConcurrentHashMap<>(8);

/**
* Optional id for this factory, for serialization purposes.
*/
@Nullable
private String serializationId;

/**
* Whether to allow re-registration of a different definition with the same name.
*/
private boolean allowBeanDefinitionOverriding = true;

/**
* Whether to allow eager class loading even for lazy-init beans.
*/
private boolean allowEagerClassLoading = true;

/**
* Optional OrderComparator for dependency Lists and arrays.
*/
@Nullable
private Comparator<Object> dependencyComparator;

/**
* Resolver to use for checking if a bean definition is an autowire candidate.
*/
private AutowireCandidateResolver autowireCandidateResolver = SimpleAutowireCandidateResolver.INSTANCE;

/**
* Map from dependency type to corresponding autowired value.
* 缓存 类型对应的自动装载的Bean
*/
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);

/**
* Map of bean definition objects, keyed by bean name.
* 缓存 beanName到BeanDefinition的映射关系
*/
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

/**
* Map from bean name to merged BeanDefinitionHolder.
*/
private final Map<String, BeanDefinitionHolder> mergedBeanDefinitionHolders = new ConcurrentHashMap<>(256);

/**
* Map of singleton and non-singleton bean names, keyed by dependency type.
* 缓存 类型 和 beanName的映射关系
*/
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);

/**
* Map of singleton-only bean names, keyed by dependency type.
* 缓存 类型 和 单例Bean names的映射
*/
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);

/**
* List of bean definition names, in registration order.
* 缓存 beanDefinition name的list
*/
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

在spring中,DefaultListableBeanFactory作为默认的功能完整的ioc容器,除了具备父类功能,还加入了BeanDefinition的管理和维护,上述代码中的beanDefinitionMap,beanDefinitionMap缓存了Bean name到 BeanDefinition的映射。

到这为止,可以看到装载BeanDefinition的类,但是单例bean不是在上面的BeanDifinition中装载的,有个DefaultSingletonBeanRegistry类专门实现了装载单例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
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

/**
* Maximum number of suppressed exceptions to preserve.
*/
private static final int SUPPRESSED_EXCEPTIONS_LIMIT = 100;


/**
* Cache of singleton objects: bean name to bean instance.
* 缓存 单例对象,最终存储单例bean的map
*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/**
* Cache of singleton factories: bean name to ObjectFactory.
* 缓存 单例工厂
*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/**
* Cache of early singleton objects: bean name to bean instance.
* 已经注册的单例对象集合,按照注册顺序排序的,并且是不可重复的。
*/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

到此为止,ioc容器作为容器的两个最重要的功能,装单例bean和装BeanDefinition。

2.5.4 再说说BeanDefinition类

spring通过定义BeanDefinition来管理应用中的各种对象以及他们之间的相互依赖关系,BeanDefinition抽象对bean的定义,是容器中的主要的数据类型。对IoC容器来说,BeanDefinition就是对依赖反转模式中管理的对象依赖关系的数据抽象,也是容器实现依赖反转功能的核心数据结构,依赖反转功能都是围绕对这个BeanDefinition的处理来完成的。

BeanDefinition的抽象数据结构如下图,

除此之外基于BeanDefiniton数据结构,spring也实现各种的BeanDefinition,

2.6 ioc容器的初始化过程

spring ioc容器的初始化过程的三大步骤:

Resource资源定位过程
BeanDefinition的载入过程
向ioc容器注册这些BeanDefinition的过程

初始化ClassPathXmlApplicationContext时会调用AbstractApplicationContext类的refresh()方法进行加载应用上下文。

refresh()方法加载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
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
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();

// 这里是子类中启动refreshBeanFactory的地方
// 1,也实现了Resource资源定位过程
// 2,BeanDefinition的载入过程
// 3,注册beanDefinition的过程
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);

try {
// 设置BeanFactory的后置处理
postProcessBeanFactory(beanFactory);

// 调用BeanFactory的后处理器,这些后处理器是在bean定义中向容器注册的
invokeBeanFactoryPostProcessors(beanFactory);

// 注册bean的后处理器,在Bean创建过程中调用
registerBeanPostProcessors(beanFactory);

// 对上下文中的消息源进行初始化
initMessageSource();

// 初始化上下文中的时间机制
initApplicationEventMulticaster();

// 初始化其他特殊的bean
onRefresh();

// 检查监听bean并且将这些bean向容器注册
registerListeners();

// 实例化所有的(非加载)bean
finishBeanFactoryInitialization(beanFactory);

// 发布容器事件,结束refresh过程
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();
}
}
}

2.6.1 Resource资源定位过程

spring的bean依赖关系倾向于配置在xml中,下面是demo程序的配置文件。资源定位过程就是找到该文件的过程。

AbstractXmlApplicationContext类中的loadBeanDefinitions()方法中可看到定位xml文件时使用的定位类XmlBeanDefinitionReader。

AbstractBeanDefinitionReader类中的loadBeanDefinition()方法中

继续调用本类中loadBeanDefinitions()方法,定位resource资源位置

其中getResources()方法最终调用的父类AbstractApplicationContext的实现。

在往里的回调用getResourceByPath()方法,这个方法都在模版模式在FileSystemXmlApplicationContext、等有实现,但是ClassPathXmlApplicationContext类没有实现,会继续调用DefaultResourceLoader类的默认实现获取resource资源。

2.6.2 BeanDefinition的载入过程

载入过程,是把定义的BeanDefinition在ioc容器中转换成一个spring内部表示的数据结构的过程,就是保存到HashMap的过程。

定位resource资源路径相同,在XmlBeanDefinitionReader类中的doLoadBeanDefinitions()方法中从xml文件中载入BeanDefinition中。

在BeanDefinitionParserDelegate类中parseBeanDefinitionElement()方法中对xml的元素解析并装配的一个BeanDefinition的属性中。

BeanDefinitionParserDelegate类的parseBeanDefinitionAttributes()方法中从xml解

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
@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {

this.parseState.push(new BeanEntry(beanName));

String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}

try {
// 创建一个BeanDefinition的实例
AbstractBeanDefinition bd = createBeanDefinition(className, parent);

// 用xml解析出的元素设置BeanDefinition的属性
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

parseMetaElements(ele, bd);
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

parseConstructorArgElements(ele, bd);
parsePropertyElements(ele, bd);
parseQualifierElements(ele, bd);

bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));

return bd;
}
catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
}
catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
}
catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
}
finally {
this.parseState.pop();
}

return null;
}

到这里就是把xml配置文件里bean属性装配到BeanDefinition中了

2.6.3 向ioc容器注册这些BeanDefinition的过程

DefaultListableBeanFactory类的registerBeanDefinition()方法中实现了beanName到Beandefinition的Map的映射,即注册了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
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {

Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");

if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
} catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}

BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
} else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
} else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
} else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
} else {
// 注册beanName 到beanDefinition的Map
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}

if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
} else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}

到这里就已经完成了从xml配置文件到ioc容器的BeanDefinition的过程,如果后面需要使用这些bean可以通过beanName获取一个实例

2.7 ioc容器的依赖注入

上面对ioc容器的设计路线和初始化过程做了简单解析。初始化过程主要完成了在ioc容器中建立BeanDefinition数据映射。在此过程中并没有发生依赖注入。

2.7.1 依赖注入过程

依赖注入的过程是用户第一次向ioc容器所要bean时触发的,不包括预初始化的bean(lazy-init属性)。如图,getBean时会依赖注入这个 bean。

摘自《spring技术内幕》

2.7.2 基类AbstractBeanFactory类中doGetBean()方法

DefaultListableBeanFactory类的基类AbstractBeanFactory类中doGetBean()方法触发依赖注入的地方。

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
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {

String beanName = transformedBeanName(name);
Object bean;

// Eagerly check singleton cache for manually registered singletons.
// 先从缓存中取的Bean,处理哪些已经被创建的单例模式Bean
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 获取一个bean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

// Check if bean definition exists in this factory.
// 检查BeanDefinition,不存在从双亲BeanFactory获取
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}

if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}

try {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

// Guarantee initialization of beans that the current 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);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}

// Create bean instance.
// 这里创建单例bean,回调lambda表达式中createBean创建Bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 这里创建属性bean的地方
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
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, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
// 这里生成对象跟factoryBean有关
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;
}
}

// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}

继续跟进createBean()方法查看其创建bean过程,createBean()方法中主要处理的是doCreateBean()方法,其实现如下:

2.7.3 关注bean的作用域配置(scope属性)

Spring中可以使用scope属性来配置bean的作用域:

  • singleton: 默认,单例,在初始化配置文件时生成单例bean对象
  • prototype:原型的,在初始化配置文件时不生成bean对象,使用时返回不同的bean对象
  • request:web环境下每一个request请求都会返回一个不同的bean,只在本次请求中有效
  • session:web环境下每一个request请求都会返回一个不同的bean,在session中有效
    所以从图中也能看到对象是单例的。
    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
    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);
    }
    // 这里创建Bean的地方
    if (instanceWrapper == null) {
    instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
    mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
    if (!mbd.postProcessed) {
    try {
    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    }
    catch (Throwable ex) {
    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    "Post-processing of merged bean definition failed", ex);
    }
    mbd.postProcessed = true;
    }
    }

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    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");
    }
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    // 这里是对bean的初始化,依赖注入往往发生在这里,
    // 这个exposedObject初始化处理完以后会返回作为依赖注入完成后的bean
    Object exposedObject = bean;
    try {
    populateBean(beanName, mbd, instanceWrapper);
    exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {
    if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
    throw (BeanCreationException) ex;
    }
    else {
    throw new BeanCreationException(
    mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
    }
    }

    if (earlySingletonExposure) {
    Object earlySingletonReference = getSingleton(beanName, false);
    if (earlySingletonReference != null) {
    if (exposedObject == bean) {
    exposedObject = earlySingletonReference;
    }
    else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
    String[] dependentBeans = getDependentBeans(beanName);
    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
    for (String dependentBean : dependentBeans) {
    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
    actualDependentBeans.add(dependentBean);
    }
    }
    if (!actualDependentBeans.isEmpty()) {
    throw new BeanCurrentlyInCreationException(beanName,
    "Bean with name '" + beanName + "' has been injected into other beans [" +
    StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
    "] in its raw version as part of a circular reference, but has eventually been " +
    "wrapped. This means that said other beans do not use the final version of the " +
    "bean. This is often the result of over-eager type matching - consider using " +
    "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
    }
    }
    }
    }

    // Register bean as disposable.
    try {
    registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
    throw new BeanCreationException(
    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
    }

接下来分别重点看一下doCreateBean()方法中的三个方法,即依赖注入的主要实现:

  • createBeanInstance()方法
  • populateBean()方法
  • initializeBean()方法

2.7.4 ioc容器的Bean的生命周期

其实容器的实现是通过ioc管理bean的生命周期来实现。ioc容器中的bean生命周期如下

  • bean实例的创建,对应createBeanInstance()方法
  • 为bean实例设置属性,对应populateBean()方法
  • 调用bean的初始化方法,对应initializeBean()方法
  • 应用可以通过ioc容器使用bean
  • 当容器关闭时,调用bean的销毁方法

2.7.5 AbstractAutowireCapableBeanFactory类的 createBeanInstance()方法

使用三种方式实例化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
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);

if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}

Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 这里用使用工厂方法对Bean进行实例化
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}

// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
// 这里用构造函数自动装配
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 使用的默认的构造函数对bean进行实例化
return instantiateBean(beanName, mbd);
}
}

// Candidate constructors for autowiring?
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}

// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}

// No special handling: simply use no-arg constructor.
// 使用的默认的构造函数对bean进行实例化
return instantiateBean(beanName, mbd);
}

在往下instantiateBean()方法中bean的实例化过程两种方式:

BeanUtils方法,它使用了JVM的反射能力
通过CGLIB来生成,CGLIB是常用的字节码生成类库,提供了一系列的API来提供生成和转换Java字节码的功能

什么时候用反射?什么时候用CGLIB呢?

当类中没有重写时用JVM的反射的方式,当有重写时用CGLIB方式。

到这里为止,bean的实例化完成了,但是Bean对象生成后,它的依赖关系并没有设置,下面会在populateBean()方法中完成完整的依赖注入过程。

2.7.6 AbstractAutowireCapableBeanFactory类的 populateBean()方法

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
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}

// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}

PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 这里开始进行依赖注入过程,先处理autowire的注入
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
// 这里对autowire注入过程,可以根据bean的名称或者类型来完成bean的自动注入
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}

boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}

if (pvs != null) {
// 这里对属性进行依赖注入
applyPropertyValues(beanName, mbd, bw, pvs);
}

其中autowireByName()方法和autowireByType()方法中对对象属性的实现主要还是通过getBean()方法来依赖注入一个bean。

最底部用applyPropertyValues()方法进行对象属性的依赖注入,包括了各种数据结构的处理(list、set、map等等)。

2.7.7 AbstractAutowireCapableBeanFactory类的 initializeBean()方法

主要实现了初始化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
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 初始化前操作
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
// 初始化方法
// 查看是否有配置init-method,来进行初始化
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 初始化后操作
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

return wrappedBean;
}

如果想要自定义bean的初始化行为,有两种方法:

使用xml配置,在bean的xml定义中指定init-method属性。
注解配置,在bean的class定义中添加@PostConstruct注解。
总体,init-method就是在创建完bean的实例后被调用的。

到这里其实依赖注入的过程就结束了。更多细节可以看看源码。

2.8 FactoryBean 与 BeanFactory 的区别

从上文可得知BeanFactory就是spring的bean工厂的顶级接口,即ioc容器。

先看看FactoryBean作用:首先它是一个Bean,但又不仅仅是一个Bean。它是一个能生产或修饰对象生成的工厂Bean,类似于设计模式中的工厂模式和装饰器模式。它能在需要的时候生产一个对象,且不仅仅限于它自身,它能返回任何Bean的实例。

再看看FactoryBean实现过程:

在doGetBean()方法中有getObjectForBeanInstance()方法生成bean实例,查看其调用链:

factoryBean为应用生成需要的对象,,只要这个bean实现了FactoryBean接口即可。

看一个case程序:

输出如下:

只要在调用getBean()方法时bean实例名称前加“&”就会用FeactoryBean的getObject()方法实例化一个对象。

3 总结

到这里基于spring5.2.x版本的ioc容器的设计与实现分享就结束了。重点理解大框架,细节方面可以在大框架的基础深入研究效果倍佳。