阿烫的后花园

烫烫烫烫烫烫

这篇文章主要讲 Spring bean 的创建过程,以及 Spring 为什么要用三级缓存来解决循环依赖的。原本是打算写 Spring 的启动过程,边读边写,断断续续快半年,内容实在太多,于是打算拆成若干个文章,此是第一篇基础。

首先奉上bean创建过程的大流程图,文章结尾还有循环依赖的另一个流程图。
bean创建流程图

三级缓存和其它较重要的变量

首先我们有个基本概念,Spring 使用三级缓存来创建 bean、解决循环依赖,三级缓存其实就是三个 Map。

缓存 说明
一级 用于存放可以使用的成品bean
二级 用于存放半成品bean,这些bean仅仅刚被创建,没有进行填充属性和实例化,用于解决循环依赖
三级 存放bean工厂对象,用于生产半成品的bean并放入第二级缓存,用于解决循环依赖

这些变量都在 DefaultSingletonBeanRegistry类下,还有其他变量,如用于标记哪些 bean 正在创建中的集合。
在这还有个 registerDependentBean 方法,很多地方出现了,这里也只是拎出来,这篇文章不需特别关注。

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
// 在  类下
// 一级缓存,存储所有创建好了的单例 bean
/** Cache of singleton objects: bean name to bean instance. */
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);

/** Set of registered singletons, containing the bean names in registration order. */
// 暂时未理解此变量的用意,这篇文章中也无需关注
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

// 标记现在正在创建的bean
/** Names of beans that are currently in creation. */
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));

/** Names of beans currently excluded from in creation checks. */
private final Set<String> inCreationCheckExclusions =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));



// dependentBeanName 依赖 beanName
// 注册依赖关系,维护了两个map,每个bean分别依赖了谁,和被谁依赖
public void registerDependentBean(String beanName, String dependentBeanName) {
String canonicalName = canonicalName(beanName);

synchronized (this.dependentBeanMap) {
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}

synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
代码块0 创建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
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

final String beanName = transformedBeanName(name);
Object bean;

// 检查缓存中的bean, 见代码块1
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
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.
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 {
final 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.
if (mbd.isSingleton()) {
// 在这开始创建 bean 了,见代码块2
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);
}

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();
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, () -> {
beforePrototypeCreation(beanName);
try {
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;
}
}

// 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) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
代码块1 解决循环依赖的核心

从三个缓存中寻找 bean,一级缓存找不到,就去二级找,二级也找不到就去三级找。入参 allowEarlyReference 用于决定是否允许在第三级缓存中寻找。

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
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
// 如果一级缓存中为空,且该bean没有正在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 尝试从二级缓存中找,处于该缓存中的bean,已经完成实例化,但未进行属性注入
singletonObject = this.earlySingletonObjects.get(beanName);
// 如果二级缓存也没有并允许提前引用的话
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 从三级缓存中拿到工厂,通过工厂获取 bean ,删除三级缓存,添加 bean 到二级缓存中
// 也就是三级缓存升级为二级缓存!
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
代码块2 创建bean前后的一些操作

主要有以下流程:

  • 如果一级缓存里有bean,直接返回。
  • 未创建,标记此bean在创建中。
  • 创建 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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
// 先尝试从一级缓存里获取bean,如果存在说明完全创建好了,则直接返回
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 这个方法很简单,就是在创建bean之前,把它放入singletonsCurrentlyInCreation 中,标记这个 bean 正在创建,如果该bean已存在了,抛出异常
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// 是否抑制异常,用于决定如果有异常,是抛出去还是放在suppressedExceptions中(不是很重要)
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 调用传过来的方法 (即 createBean(beanName, mbd, args) ) 见代码块4
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 此方法也很简单,将 singletonsCurrentlyInCreation 容器中对应的 bean 移除掉
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 如果是个新的bean,添加到一级缓存中,见代码块3
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
代码块3 将bean添加到一级缓存

这是将 bean 添加到一级缓存,同时移除二三级缓存,逻辑很简单。

1
2
3
4
5
6
7
8
9
10
11
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 添加到一级缓存中
this.singletonObjects.put(beanName, singletonObject);
// 从二、三级缓存中移除
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
// 按顺序添加到已注册的bean中去
this.registeredSingletons.add(beanName);
}
}
代码块4 在创建bean之前尝试走代理

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

RootBeanDefinition mbdToUse = mbd;

// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}

// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}

try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 给BeanPostProcessors一个返回代理而不是目标bean实例的机会。
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);
}

try {
// 创建bean的更具体过程,见代码块5
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
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
// 在实例化之前解决
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 直接执行 BeanPostProcessor 初始化完成后的方法,跳过其他初始化方法(实例化之后,初始化之前)
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
// 找到所有的 BeanPostProcessor
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
// 判断 BeanPostProcessor 是否是 InstantiationAwareBeanPostProcessor, 只有这个接口更强大,有在bean实例化之前的钩子
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
// 如果接口返回了一个对象,那就使用这个对象,所以执行顺序很重要
if (result != null) {
return result;
}
}
}
return null;
}

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) {
Object result = existingBean;
// 执行每个 BeanPostProcessor 的 postProcessAfterInitialization 接口
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
// 如果有一个为 null, 那就直接返回
if (current == null) {
return result;
}
result = current;
}
return result;
}
代码块5 创建bean的实际过程

主要三个步骤:

  1. 实例化
  2. 填充属性
  3. 初始化 (Aop等)
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
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {

// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 实例化 bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final 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.
// 立刻缓存单例bean,但有三个条件,单例、允许循环引用、该bean正在创建中
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// 添加到三级缓存,见代码块6
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

// Initialize the bean instance.
Object exposedObject = bean;
try {
// 填充属性,主要就是处理 @Autowired,这边展开来会很多,放在下次
populateBean(beanName, mbd, instanceWrapper);
// 初始化 bean,如果需要aop代理,会在此时进行,见代码块7
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) {
// 这部分是很重要的代码
// 这里去缓存里拿自己,为什么要这样做呢,因为缓存中可能是自己的代理对象,要用代理对象替换掉原始对象返回。但上面不是已经被初始化了,已经是代理对象了吗,其实不一定。
// 情况1: A 类是在初始化自己,如果 A 需要被代理,那么上面初始化的时候 exposedObject 的确会变成自己的代理对象。
// 情况2: 在为 A 注入 B 属性的时候,B 依赖 A ,在三级缓存中找到了 A 的工厂,执行工厂方法生成了 A 的代理对象并注入进 B,最后返回 A 执行 A 的初始化,尝试代理的时候发现已经被代理过了,所以就不需要走代理了,exposedObject == bean, 都是原始对象。
// 拿到的可能为自己的代理对象,也可能为自己本身。注意第二个参数为 false 了,不再从第三级缓存拿取。如果前两级缓存没有,那一定在第三级,而第三级缓存里的工厂只能被别的循环依赖的 bean 执行,因此,如果 earlySingletonReference 为空,说明没有发生循环依赖。
Object earlySingletonReference = getSingleton(beanName, false);
// 如果是情况1,此时不管 A 是否需要被代理, earlySingletonReference为null,表明没有发生循环依赖,所以直接返回 exposedObject,它可能是本身,如果aop了话,就是代理类。
// 如果是情况2,能取到一个值,说明发生了循环依赖。earlySingletonReference 可能是代理对象,也可能是原始对象(不需要代理)
if (earlySingletonReference != null) {
// 这个判断正常情况下一定是正确的,除非你在后置处理器中替换掉这个 bean (请不要做这种只会徒增烦恼的骚操作。)
// 为什么如果被 aop 了,也是相等的呢,exposedObject 不应该是被代理的对象了吗?解释见代码块7
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;
}

这就是上面说的骚操作,在正常流程中替换一个 bean,请不要这样做。

1
2
3
4
5
6
7
8
9
10
@Component
public class MyPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("a")) {
return new A();
}
return bean;
}
}
代码块6 添加到三级缓存

将bean添加到三级缓存中,添加的是该bean的ObjectFactory,一个工厂

1
2
3
4
5
6
7
8
9
10
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}

此方法是 ObjectFactory 的具体内容,就是找到所有的 SmartInstantiationAwareBeanPostProcessor 并执行其 getEarlyBeanReference 方法

1
2
3
4
5
6
7
8
9
10
11
12
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}

其中最重要的 SmartInstantiationAwareBeanPostProcessor 是 AbstractAutoProxyCreator,用于处理代理的,其方法如下:

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 Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}

// 如果需要的话,就包装这个bean
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

// Create proxy if we have advice.
// 如果被切面了,就代理
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}

this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
代码块7 初始化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
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 调用 aware 方法
invokeAwareMethods(beanName, bean);
}

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 调用初始化之前的钩子
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
// 初始化
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 实现了 Aware 接口,就调用对应的方法,把值设置进去。
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}

// 执行初始化之前的钩子
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {

Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}

// 执行实例化之后的钩子
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {

Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}

初始化 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
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {

boolean isInitializingBean = (bean instanceof InitializingBean);
// 如果 bean 实现了 InitializingBean 接口,就执行其 afterPropertiesSet 方法
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
} catch (PrivilegedActionException pae) {
throw pae.getException();
}
} else {
((InitializingBean) bean).afterPropertiesSet();
}
}

// 如果在 xml 中指定了 bean 的 init-method
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
// 满足某些判断条件后,反射调用指定的init方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}

上面提到了 AbstractAutoProxyCreator 类的 getEarlyBeanReference 方法,里面调用了 wrapIfNecessary 方法,这个类也实现了初始化之后的钩子,用于aop代理。虽然有多个地方尝试进行包装代理,但实际上一个对象只能被代理一次,要不然会出现多个实例了,毕竟每次执行代理都产生一个新的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// remove 方法的返回值很重要,返回值就是 cacheKey 对应的值,如果不存在肯定进入逻辑,如果不为null ,说明没被 getEarlyBeanReference 处理过,只有那一个地方对 earlyProxyReferences 设置值了。
// (我认为,不会有存在这个key,但取出来的值却和 bean 不一样的情况,不知道为什么要这样写。)
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 如果需要代理的话就包装一下
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}

// 把之前提到的代码粘过来作对比
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 放入 earlyProxyReferences ,用意是标记 bean 已经被early 处理过了
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}

到这里, bean 的创建过程基本就结束了。我们再用一个例子来加深理解,下图是 Chicken 和 Egg 相互循环依赖的时的创建过程, Chicken 需要被代理, Egg 无所谓是否需要代理,流程都是这样:

代理Chicken 和 Egg 循环依赖时的创建过程

为什么需要三级缓存?

如果只用二级缓存可以吗,会有什么问题呢?也是可以的,解决循环依赖有两种选择:

  1. 不管有没有依赖,实例化后都立刻创建好代理对象,并将半成品对象放入缓存,出现循环依赖时,其他对象直接取出代理对象注入即可。这种只需要二级缓存即可。
  2. 不提前创建代理对象,在出现循环引用,被其它对象注入的时,才生产代理对象。如果没有出现循环引用,就按 Spring 的设计原则走。

Spring采用的是第二种选择, Spring 的设计原则是如果没有循环依赖,通过 AnnotationAwareAspectJAutoProxyCreator 这个初始化后置处理器来在 bean 生命周期的最后一步来完成 Aop 代理,而不是实例化之后立刻进行 Aop 代理。如果出现循环依赖,要想不在实例化之后立刻 Aop 代理,只能引入第三级工厂缓存,在其他 bean 在注入自己的时候,执行 getEarlyBeanReference ,进行代理,然后注入。

但是,由于在 getBean 的时候,它也不知道有没有循环依赖,于是所有 bean 的都先将 getEarlyBeanReference 工厂添加到三级缓存中,只不过没有循环依赖的时候,完全不会用到第三级缓存罢了,有循环依赖,就执行,放入二级缓存。


参考:
面试必杀技,讲一讲Spring中的循环依赖
曹工说Spring Boot源码(29)– Spring 解决循环依赖为什么使用三级缓存,而不是二级缓存
Spring循环依赖三级缓存是否可以减少为二级缓存?

Kotlin中的协程是什么

协程能做的,Java线程都能够做,kotlin协程只是一套封装较好的java线程api。

为什么需要引入协程?

  • 节省资源,轻量,无非就是
    • 节省内存,每个线程都需要分配一段栈内存,以及其他一些资源。
    • 节省分配线程的开销,创建和销毁都要进行系统调用
    • 大量线程切换带来的开销
  • 与nio配合实现非阻塞的编程,提高系统的吞吐、
  • 使用起来更加顺畅,跑起来是异步的,写起来是同步的。

分别来看,web中,tomcat线程数量一般在50-500,spring默认给200。假如每个线程128kb,500个线程才多大呢?

在看分配线程的开销,Java线程池可以很好的解决问题,vertx、kotlin协程本质都是使用线程池实现的,又有多少开销呢?

线程的切换实际只会发生在活跃的线程上,在web场景中,大量的请求会因为io(发请求、db)挂起,根本不会参与操作系统的线程切换,为了减少线程切换的开销,真正要防范的是同时有大量活跃线程

再说 nio,Java NIO/Netty/Vert.X/rxJava/Akka可以任意选择。一般来讲,Netty可以解决绝大部分因为IO的等待造成资源浪费的问题

Java仅仅是没有解决”协程“在Java中的定义,以及“写得优雅“这个问题。

什么时候适合用协程

线程调度是被动调度,协程调度是主动调度。

在传统Java线程中,如果想要跑满CPU,在一些高并发,io密集型场景中,其效率不如协程。因为线程模型在遇到需要等待的地方时(如 io),并不会主动交出线程,需要创建更多线程来抢占CPU时间片,Java线程模型是1:1的,会创建大量操作系统级线程,并由操作系统进行管理调度,调度时机是随机的,频繁的调度会产生不小的开销。

而协程的调度是用户态进程内runtime管理的,这个过程没有操作系统的线程调度的干预,这就需要协程主动交出执行权,通常就是io。

如果是纯计算场景,程序中无需等待,线程又不是很多,那完全使用线程就足够了。

Kotlin中的协程是什么

首先协程能做的,Java线程都能够做,Kotlin协程只是一套封装较好的Java线程api,她是“假协程”,非“真协程”

为什么需要引入协程?

  • 节省资源,轻量,无非就是
    • 节省内存,每个线程都需要分配一段栈内存,以及其他一些资源。
    • 节省分配线程的开销,创建和销毁都要进行系统调用
    • 大量线程切换带来的开销
  • 与nio配合实现非阻塞的编程,提高系统的吞吐、
  • 使用起来更加顺畅,跑起来是异步的,写起来是同步的。

一条条来看,在 Web 服务中,Tomcat 线程数量一般在50-500,Spring默认给 200 个线程。假如每个线程128kb,500个线程才多大呢?可以忽略不计了吧。

再看分配线程的开销。Java线程池可以很好的解决问题,vertx、kotlin协程本质都是使用线程池实现的,又有多少开销呢?

再看切换线程的开销。线程的切换实际只会发生在活跃的线程上,在web场景中,大量的请求会因为io(发请求、db)挂起,根本不会参与操作系统的线程切换,为了减少线程切换的开销,真正要防范的是同时有大量活跃线程

再说 nio。Java NIO/Netty/Vert.X/rxJava/Akka可以任意选择。一般来讲,Netty可以解决绝大部分因为IO的等待造成资源浪费的问题。

Java仅仅是没有解决“协程”在Java中的定义,以及“写得优雅“这个问题。

什么时候适合用协程

线程调度是被动调度,协程调度是主动调度。

在传统Java线程中,如果想要跑满CPU,在一些高并发,io密集型场景中,其效率不如协程。因为线程模型在遇到需要等待的地方时(如 io),并不会主动交出线程,需要创建更多线程来抢占CPU时间片,Java线程模型是1:1的,会创建大量操作系统级线程,并由操作系统进行管理调度,调度时机是随机的,频繁的调度会产生不小的开销。

而协程的调度是用户态进程内runtime管理的,这个过程没有操作系统的线程调度的干预,这就需要协程主动交出执行权,通常就是io。

如果是纯计算场景,程序中无需等待,线程又不是很多,那完全使用线程就足够了。

对象的内存布局

在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。

本文不讨论对象头中里面有什么,在32位系统中,对象头占8字节;在64位系统中(未开启指针压缩),对象头占16字节。

第二部分实例数据就是对象真正存储的有效数据,也就是咱们在类中定义的变量。之前在这篇 为什么short、byte会被提升为int,及基本类型的真实大小 文章中讨论过,short、byte、boolean 等类型在栈中实际也都是占用4字节,但是在堆中不必哦,例如 byte 数组,每个元素就占一字节,在其它对象中,byte也只占一字节。

第三部分对齐填充并不一定是必需存在的,仅仅是占位符的作用。由于虚拟机都要求对象起始地址必须是8字节的整数倍,所以对象的大小也必须是8字节的整数倍。当对象实例数据部分没有对齐时,就需要对齐填充来补全。(64位开启指针压缩后,对象头只有12字节,也可能会对齐填充,哪不齐就填哪,不是一定在末尾)

JOL工具

本文使用 JOL 工具测量对象的大小,JOL全称为Java Object Layout,是分析JVM中对象布局的工具,添加依赖:

1
implementation("org.openjdk.jol:jol-core:0.14")

使用方式,可以传 类 或者 实例对象。

1
2
3
System.out.println(ClassLayout.parseInstance(yourObject).toPrintable());
// or
System.out.println(ClassLayout.parseClass(Test.class).toPrintable());

影响对象大小的启动参数

这节会讨论一些会影响对象大小的启动参数,所有启动参数的解释都可以在源码中找到: http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/tip/src/share/vm/runtime/globals.hpp?utm_source=ld246.com

CompactFields

-XX:+CompactFields :在前一个字段之间的空白处分配非静态字段,默认开启。

开启该参数后,比较窄的变量可能会打破原有顺序,插入到更前的空隙位置中。

1
2
3
4
5
6
// 测试类
class A {
private boolean a;
private char b;
private long e;
}

开启CompactFields

关闭CompactFields

UseCompressedOops

由于在32位系统中,最大获取的空间地址为 4GB,对于有些应用而言不够,因此需要使用64位系统。

之前说了,在64位系统中,对象头所占空间更大,有16字节,不仅如此,原本占4字节的对象指针在64位系统中(未开启指针压缩)也膨胀了一倍,变为8字节,因此在64位系统下,会着实浪费不少内存空间。

此时,我们就可以开启指针压缩了。
-XX:+UseCompressedOops:开启指针压缩,只对 64 位系统有效,默认开启

以下是测试类A

1
2
3
4
5
6
7
8
9
10
class A {
private short a;
private char b;
private long e;
private Object f;

public static void main(String[] args) {
System.out.println(ClassLayout.parseInstance(new A()).toPrintable());
}
}

类A 不开启指针压缩

类A 开启指针压缩

再看看数组对象的压缩情况:

1
2
3
public static void main(String[] args) {
System.out.println(ClassLayout.parseInstance(new Object[10]).toPrintable());
}

数组对象不开启指针压缩

数组对象开启指针压缩
发现开启压缩后,对象头的大小由20字节(比普通对象大是因为要多存储数组大小)变为16字节,且少了一个4字节的对齐填充。

64位系统下开启指正压缩后,有以下变化:

  • 对象头由 16 字节变为 12 字节。
  • 对象引用由 8 字节变为 4 字节。
  • 数组对象的对象头由20字节变为16字节。(由于还少了一次对齐填充,能压缩8字节对象头)

AutowiredAnnotationBeanPostProcessor 是一个非常重要的后置处理器,主要用于为 bean 填充属性。

类图如下:
image.png

该处理器实现了 InstantiationAwareBeanPostProcessor 接口,最重要的就是 postProcessProperties 方法,用于填充 bean 的属性。

构造器

该类只有一个构造方法,该方法设置了 AutowiredAnnotationBeanPostProcessor 能够支持哪些注解,默认有 Autowired、Value、和 Inject, Inject 则是 JSR-330 的标准。

1
2
3
4
5
6
7
8
9
10
11
12
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
依赖注入 populateBean 方法调用的主入口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 寻找需要自动装配的元数据
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
// 为元数据注入
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
寻找需要自动装配的元数据

简而言之,就是先尝试从缓存拿,拿不到就去构建,构建完再放入缓存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
构建需要自动装配的元数据
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
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}

List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;

do {
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

// 处理每一个字段
ReflectionUtils.doWithLocalFields(targetClass, field -> {
// 在字段上寻找自动装配的注解
MergedAnnotation<?> ann = findAutowiredAnnotation(field);
// 如果没有注解,就去找下一个字段
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
// 不支持自动装配静态属性
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static fields: " + field);
}
return;
}
// 判断这个属性是否必须装配
boolean required = determineRequiredStatus(ann);
// 添加到当前元素列表
currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement(field, required));
}
});

// 处理每一个方法
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
// 静态方法不支持自动装配
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isInfoEnabled()) {
logger.info("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement(method, required, pd));
}
});

elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
// 递归寻找父类的字段和方法
while (targetClass != null && targetClass != Object.class);

return InjectionMetadata.forElements(elements, clazz);
}

@Nullable
private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
MergedAnnotations annotations = MergedAnnotations.from(ao);
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
MergedAnnotation<?> annotation = annotations.get(type);
if (annotation.isPresent()) {
return annotation;
}
}
return null;
}
注入
1
2
3
4
5
6
7
8
9
10
11
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectionMetadata.InjectedElement> checkedElements = this.checkedElements;
Collection<InjectionMetadata.InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectionMetadata.InjectedElement element : elementsToIterate) {
// 为每个元素注入,元素可能是字段属性,也可能是方法,两者都继承了 InjectedElement,多态。
element.inject(target, beanName, pvs);
}
}
}
按属性注入

流程很清晰,就是获取依赖的 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
private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {

private final boolean required;

private volatile boolean cached = false;

@Nullable
private volatile Object cachedFieldValue;

public AutowiredFieldElement(Field field, boolean required) {
super(field, null);
this.required = required;
}

@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
// 解析依赖,如果依赖的bean 还未实例化,就实例化,因此此处会有循环依赖的问题
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new AutowiredAnnotationBeanPostProcessor.ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
if (value != null) {
// 为这个属性注入值
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
}
按方法注入

也就是常说的 set注入。
流程也比较清晰,找到方法上的所有参数,依次获取 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
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
if (checkPropertySkipping(pvs)) {
return;
}
Method method = (Method) this.member;
Object[] arguments;
if (this.cached) {
// Shortcut for avoiding synchronization...
arguments = resolveCachedArguments(beanName);
}
else {
int argumentCount = method.getParameterCount();
arguments = new Object[argumentCount];
DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
for (int i = 0; i < arguments.length; i++) {
MethodParameter methodParam = new MethodParameter(method, i);
DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
currDesc.setContainingClass(bean.getClass());
descriptors[i] = currDesc;
try {
// 依次解析依赖
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
if (arg == null && !this.required) {
arguments = null;
break;
}
arguments[i] = arg;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
}
}
synchronized (this) {
if (!this.cached) {
if (arguments != null) {
DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length);
registerDependentBeans(beanName, autowiredBeans);
if (autowiredBeans.size() == argumentCount) {
Iterator<String> it = autowiredBeans.iterator();
Class<?>[] paramTypes = method.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
String autowiredBeanName = it.next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
cachedMethodArguments[i] = new AutowiredAnnotationBeanPostProcessor.ShortcutDependencyDescriptor(
descriptors[i], autowiredBeanName, paramTypes[i]);
}
}
}
this.cachedMethodArguments = cachedMethodArguments;
}
else {
this.cachedMethodArguments = null;
}
this.cached = true;
}
}
}
if (arguments != null) {
try {
// 反射调用方法
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}

invokeBeanFactoryPostProcessors 在 Spring 启动流程中,是非常重要的一个步骤,此阶段会实例化并调用所有注册的 BeanFactoryPostProcessor beans。

方法有两个入参,分别是 工厂 beanFactory 和 初始的List<BeanFactoryPostProcessor>。

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
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();

if (beanFactory instanceof BeanDefinitionRegistry) {
// beanFactory 默认是 DefaultListableBeanFactory 类型,实现了 DefaultListableBeanFactory 接口,会走进这个条件里
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

// beanFactoryPostProcessors 是方法传进来的参数,里面有三个BeanFactoryPostProcessor,他们对本文不重要。判断类型如果是 BeanDefinitionRegistryPostProcessor 就调用 postProcessBeanDefinitionRegistry 方法,并添加到 registryProcessor 中;如果不是,就先添加到 regularPostProcessors 中。之后会一起调用这两个集合中 BeanFactoryPostProcessor实例的postProcessBeanFactory方法。
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}

// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 首先获取所有实现了 PriorityOrdered 优先级接口的 BeanDefinitionRegistryPostProcessor,这个接口有能力添加 beanDefinition 到 beanFactory 中,这次只会找到一个 ConfigurationClassPostProcessor ,这是Spring最重要的一个处理器,它会找到 basePackages 下的所有 bean 的候选类,生成 beanDefinition 并添加到 beanFactory 中。下面会详谈这个处理器。
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 创建这个 bean
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 标记这个处理器已经执行过,防止重复执行
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 下面两行代码会出现很多次,把 BeanDefinitionRegistryPostProcessor 放到一个list 里是为了最后调用它们实现 BeanFactoryPostProcessor 接口的方法。因此,BeanDefinitionRegistryPostProcessor 的执行时机是早于所有的 BeanFactoryPostProcessor 的。
registryProcessors.addAll(currentRegistryProcessors);
// 因此调用 BeanDefinitionRegistryPostProcessor 的接口
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();

// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// 其次,获取实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessor, 和上面一样的流程,只是优先级的区别罢了。
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();

// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// 最后,执行那些不带优先级注解的 BeanDefinitionRegistryPostProcessors 直到不再出现新的 BeanDefinitionRegistryPostProcessor 。为什么会出现呢,因为 BeanDefinitionRegistryPostProcessor 可以注册 BeanDefinitionRegistryPostProcessor 类型的 beanDefinition,所以就要用while循环不停地寻找了。
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 出现了新的 BeanDefinitionRegistryPostProcessor, 标记为已执行,并且设置需要继续循环
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}

// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 走到了这里的时候,所有的 BeanDefinitionRegistryPostProcessor 已经调用完其 postProcessBeanDefinitionRegistry() 方法了,这些处理器也都存了下来。由于 BeanDefinitionRegistryPostProcessors 还继承了 BeanFactoryPostProcessor ,因此还需要调用所有 BeanDefinitionRegistryPostProcessor 的 postProcessBeanFactory() 方法
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}

else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}

// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// 下面的流程比较简单,找出所有的 BeanFactoryPostProcessor ,并按照其优先级依次调用其 postProcessBeanFactory() 方法。
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}

// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}

BeanDefinitionRegistryPostProcessor

在上面的代码中,逻辑比较清晰,主要有两步:找出所有BeanDefinitionRegistryPostProcessor,并按优先级依次调用;找出所有 BeanFactoryPostProcessor 并按优先级依次调用。

那 BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor 有什么区别呢?这父子俩源码如下:

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

public interface BeanFactoryPostProcessor {

/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}


/**
* Extension to the standard {@link BeanFactoryPostProcessor} SPI, allowing for
* the registration of further bean definitions <i>before</i> regular
* BeanFactoryPostProcessor detection kicks in. In particular,
* BeanDefinitionRegistryPostProcessor may register further bean definitions
* which in turn define BeanFactoryPostProcessor instances.
*
* @author Juergen Hoeller
* @since 3.0.1
* @see org.springframework.context.annotation.ConfigurationClassPostProcessor
*/
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

BeanDefinitionRegistryPostProcessor 继承了 BeanFactoryPostProcessor,根据源码,其执行时机也是早于 BeanFactoryPostProcessor 的,在 自定义BeanFactoryPostProcessor的错误做法 中有介绍过 BeanFactoryPostProcessor 接口。

简而言之, BeanFactoryPostProcessor 允许你修改 BeanDefinition,BeanDefinitionRegistryPostProcessor 允许你动态的注册 BeanDefinition。

阅读全文 »

BeanFactoryPostProcessor 介绍

Spring提供了很多个扩展点,包括BeanFactoryPostProcessor、BeanPostProcessor、Aware,今天主要讲述下 BeanFactoryPostProcessor 的功能及错误用法。

BeanFactoryPostProcessor 能做什么?先贴下源代码。

阅读全文 »

Spring中有三种初始化Bean的方式:

  • 对初始化方法添加注解 @PostConstruct
  • 实现 InitializingBean 接口
  • 实现 SmartInitializingSingleton 接口

首先要测试三种初始化的执行顺序,如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Component
public class InitTest implements InitializingBean, SmartInitializingSingleton {

@PostConstruct
public void postConstruct() {
System.out.println("@PostConstruct");
}

@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet");
}

@Override
public void afterSingletonsInstantiated() {
System.out.println("afterSingletonsInstantiated");
}
}

image.png

执行顺序显而易见,接下开是要说下这三种方式都是在什么地方进行执行的。

阅读全文 »

自旋锁与自适应锁

  当两个线程都需要访问某个共享资源时,常用互斥同步(synchronized)来保证并发正确性,即共享数据在同一时刻只被一个线程使用,其余线程暂时挂起(即Java中的线程阻塞状态)。但假如共享数据的锁定只会持续很短的时间,为了这段时间去挂起和恢复线程并不划算,因此可以让后面请求锁的线程“稍等一下”,但不放弃处理器的执行时间,看看持有锁的线程是否很快就会释放锁。为了让线程等待,我们只需要让线程执行一个忙循环(自旋),这就是自旋锁

阅读全文 »

线程的实现

  实现线程主要有 3 种方式:使用内核线程实现、使用用户线程实现、使用用户线程加轻量级进程混合实现。

1.使用内核线程实现

  内核线程(Kernel-Level Thread,KLT)就是直接由操作系统内核支持的线程,这种线程由内核来完成线程切换,内核通过操作调度器对线程进行调度,并负责将线程的任务映射到各个处理器上。每个内核线程可以视为内核的一个分身,这样操作系统就有能力同时处理多个任务,支持多线程的内核叫做多线程内核

  程序一般不会直接去使用内核线程,而是使用内核线程的一种高级接口——轻量级进程(Light Weight Process,LWP),也就是我们通常意义上所讲的线程。由于每个轻量级进程都由一个内核线程支持,因此只有先支持内核线程,才能有轻量级进程。这种轻量级进程和内核线程之间 1 : 1 的关系称为一对一的线程模型,如下图。

image.png

  由于是基于内核线程实现的,所以各种线程操作,如创建、析构及同步,都需要进行系统调用。而系统调用的代价相对较高,需要在用户态和内核态中来回切换,其次,每个轻量级进程都需要一个内核线程的支持,因此轻量级进程要消耗一定的内核资源(如内核线程的栈空间),因此,一个系统支持的轻量级进程的数量是有限的。

  Sun JDK 的 windows 版与 Linux 版都是使用此模型实现的。

2.使用用户线程实现

  广义上讲,一个线程只要不是内核线程,就可以认为是用户线程(User Thread,UT),那轻量级进程也属于用户线程,但轻量级进程的实现始终是建立在内核之上的,许多操作都要进行系统调用,效率会受到限制。

  狭义上的用户线程是指完全建立在用户控件的线程库上,系统内核不能感知线程存在,用户线程的建立、同步、销毁和调度完全在用户态中完成,不需要内核的帮助。这种线程是不需要切换到内核态,因此操作时非常快速且低消耗的。这种实现可以支持规模更大的线程数量,这种进程与用户线程之间 1 : N 的关系称为一对多的线程模型。

image.png

  使用用户线程的优势在于不需要系统内核支援,劣势也在于没有系统内核的支援,所有的线程操作都需要用户程序自己处理,创建、切换、调度、销毁都非常复杂。现在使用蔗渣模型的程序越来越少了,Ruby、Java曾经使用过用户线程,最终又放弃了它。

3.使用用户线程加轻量级进程混合实现

  许多Unix操作系统,如 Solaris、HO-UX 提供了 N : M 的线程模型实现,这种模型其实就是将上面两种方式混合,如下图:
image.png

Java线程调度

  线程调度是指系统为线程分配处理器使用权的过程,主要调度方式有两种:协同式线程调度抢占式线程调度。

  协同式调度的多线程系统中,线程的执行时间是由线程本身来控制的,线程把自己的工作执行完了后,要主动通知系统切换到另外一个线程上。这种实现的最大好处是实现简单,切换操作对于线程自己事可知的,所以没有线程同步的问题。坏处也很明显:线程执行时间不可控,甚至如果一个线程编写有问题,一直不告诉系统进行线程切换,那程序就会阻塞,甚至系统崩溃。

  如果使用抢占式调度的多线程系统,那么每个线程将由系统来分配执行时间,线程的切换不由线程本身来决定。Java使用的就是抢占式调度

操作系统中的线(进)程状态转换

  首先要简单说下操作系统中线程的状态,其有五个状态,除了创建和终止,还有就绪、运行和阻塞状态,当发生 I/O 或其它事件时,会从运行状态转变为阻塞状态,当 I/O 结束时,便从阻塞状态转变为就绪状态,此时只要有 CPU 时间片就可以立即变为运行状态。
进程转换状态

不难发现操作系统中的线程状态都是围绕着 CPU 来说的

Java线程状态转换

  Java线程定义了 6 种线程状态:

  • 新建(New):创建后尚未启动的线程处于这种状态。
  • 运行(Runbale):包括了操作系统线程状态中的 Running 和 Ready,也就是处于此状态的线程可能正在执行,也可能正在等待 CPU 为它分配执行时间。
  • 无限期等待(Waiting):处于这种状态的线程不会被分配 CPU 时间,它们要等待被其它线程显示地唤醒,以下方法会让线程陷入此状态:
    • 没有设置 timeout 参数的 Object.wait() 方法。
    • 没有设置 timeout 参数的 Thread.join() 方法。
    • LockSupport.park() 方法。
  • 期限等待(Timed Waiting):处于这种状态的线程不会被分配 CPU 时间,不过无须等待被其它线程显示地唤醒,在一定时间后它们会由系统自动唤醒,以下方法会让线程陷入此状态:
    • Thread.sleep() 方法。
    • 设置了 timeout 参数的 Object.wait() 方法。
    • 设置了 timeout 参数的 Thread.join() 方法。
    • LockSupport.parkNanos() 方法。
    • LockSupport.parkUntil() 方法。
  • 阻塞(Blocked):线程被阻塞了,阻塞与等待的区别是阻塞是在等待着获取到一个排它锁,这个事件将在另外一个事件放弃这个锁的时候发生,而等待状态则是在等待一段时间或唤醒动作的发送。当程序进入同步区域的时候,线程将进入阻塞状态。
  • 结束(Terminated):线程已经结束执行。

  需要注意的是,Java中的线程状态并不是与操作系统中的线程状态一一对应的。查看 Thread 类的源代码,可以看见 RUNNABLE 状态的注释中说了处于这个状态线程可能正在 JVM 中执行,也可能正在等待操作系统的某种资源。所以,RUNNABLE 状态至少包括了操作系统中的就绪和运行状态的。

1
2
3
4
5
6
7
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE

  当发生 I/O 阻塞时,操作系统概念下的线程会切换到阻塞状态,但 Java 的线程状态也有阻塞,还有无期限等待和期限等待,那此时 Java 的线程状态是什么呢?其实也还是 RUNNABLE,可以写一个简单 demo 来验证:

image.png

  同理,网络阻塞时,Java的线程状态也还是 RUNNABLE。Java 中的 RUNNABLE 实际对应了操作系统中的 就绪状态、运行状态和部分阻塞状态。看起来很混乱,那 Java 为什么要这么做呢?前面 RUNNABLE 的注释说到该状态的线程可能正在JVM中执行,也可能正在等操作系统的资源,JVM 把很多东西都看作了资源,硬盘、CPU、网卡也罢,只要有一个东西在为线程服务,那就可以理解为这个线程是在“执行”的,虽然 I/O 阻塞, CPU 不执行了,但网卡还在监听干活啊,只是暂时没有数据罢了。操作系统的线程状态都是围绕着 CPU 来说的,这与 JVM 的侧重点不同。

  如果 Java 中的线程处于期限等待、无期限等待或阻塞状态,那说明这个线程真的是一点事都不干了,而且是你自己不让它干的,例如调用了 sleep()、wait() 方法。

参考:https://my.oschina.net/goldenshaw/blog/705397

0%