- + - @@ -347,7 +347,7 @@
-
- Spring Bean 加载过程
-
diff --git a/archives/2020/08/index.html b/archives/2020/08/index.html
index 5cb2fa4a..9a8aec9a 100644
--- a/archives/2020/08/index.html
+++ b/archives/2020/08/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2020/index.html b/archives/2020/index.html
index 4c74ba98..18e0f275 100644
--- a/archives/2020/index.html
+++ b/archives/2020/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/05/index.html b/archives/2023/05/index.html
index 539bcf0e..183b92da 100644
--- a/archives/2023/05/index.html
+++ b/archives/2023/05/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/06/index.html b/archives/2023/06/index.html
index be634e2c..5272063f 100644
--- a/archives/2023/06/index.html
+++ b/archives/2023/06/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/07/index.html b/archives/2023/07/index.html
index 7f1c535f..1cb43f2f 100644
--- a/archives/2023/07/index.html
+++ b/archives/2023/07/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/tags/Java/index.html b/archives/2023/08/index.html
similarity index 70%
rename from tags/Java/index.html
rename to archives/2023/08/index.html
index 94638b7d..4aa36998 100644
--- a/tags/Java/index.html
+++ b/archives/2023/08/index.html
@@ -22,7 +22,7 @@
-
+
@@ -30,14 +30,14 @@
-
+
-
+
-标签: Java | Moralok
+归档 | Moralok
@@ -68,7 +68,7 @@
- Moralok
+ Moralok
@@ -158,7 +158,7 @@
@@ -186,7 +186,7 @@
-
+
@@ -195,9 +195,7 @@
- Java
- 标签
-
+ 嗯..! 目前共计 18 篇日志。 继续努力。
@@ -209,15 +207,15 @@ Java
@@ -225,105 +223,6 @@ Java
-
-
-
-
- Java 垃圾收集
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 字符串常量池的测试和分析
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/archives/2023/11/index.html b/archives/2023/11/index.html
index 38cea205..ece70fec 100644
--- a/archives/2023/11/index.html
+++ b/archives/2023/11/index.html
@@ -158,7 +158,7 @@ Moralok
@@ -203,26 +203,6 @@ Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Spring Bean 加载过程
-
-
-
-
-
-
-
-
-
- Spring Bean 生命周期
-
-获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
-1
2
3
4
public Object getBean(String name) throws BeansException {
// 具体工作由 doGetBean 完成
return doGetBean(name, null, null, false);
}
-
-deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
-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
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换名称:去除 FactoryBean 的前缀 &,将别名转换为规范名称
final String beanName = transformedBeanName(name);
Object bean;
// 检查单例缓存中是否已存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
// 如果已存在,直接返回该实例或者使用该实例(FactoryBean)创建并返回对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果当前 Bean 是一个正在创建中的 prototype 类型,表明可能发生循环引用
// 注意:Spring 并未解决 prototype 类型的循环引用问题,要抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果当前 beanFactory 没有 bean 定义,去 parent beanFactory 中查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 标记为至少创建过一次
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保 bean 依赖的 bean(构造器参数) 都已实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 注意:Spring 并未解决构造器方法中的循环引用问题,要抛异常
}
// 注册依赖关系,确保先销毁被依赖的 bean
registerDependentBean(dep, beanName);
// 递归,获取依赖的 bean
getBean(dep);
}
}
}
if (mbd.isSingleton()) {
// 如果是单例类型(绝大多数都是此类型)
// 再次从缓存中获取,如果仍不存在,则使用传入的 ObjectFactory 创建
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>(
{
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);
}
else if (mbd.isPrototype()) {
// 如果是原型类型,每次都新创建一个
// ...
}
else {
// 如果是其他 scope 类型
// ...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
-
-getSingleton
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 加锁
synchronized (this.singletonObjects) {
// 再次从缓存中获取(和调用前从缓存中获取构成双重校验)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
// 如果正在销毁单例,则抛异常
// 注意:不要在销毁方法中调用获取 bean 方法
}
// 创建前,先注册到正在创建中的集合
// 在出现循环引用时,第二次进入 doGetBean,用此作为判断标志
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// ...
try {
// 使用传入的单例工厂创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 如果异常的出现是因为 bean 被创建了,就忽略异常,否则抛出异常
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
// ...
}
finally {
// ...
// 创建后,从正在创建中集合移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加单例到缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
-
-创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
-1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// ...
try {
// 给 Bean 后置处理器一个返回代理的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...
// 常规的创建 Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
-
-doCreateBean
常规的创建 Bean 的具体工作是由 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
39
40
41
42
43
44
45
46
47
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 使用相应的策略创建 bean 实例,例如通过工厂方法或者有参、无参构造器方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// ...
// 使用 ObjectFactory 封装实例并缓存,以解决循环引用问题
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
// 填充属性(包括解析依赖的 bean)
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
// ...
// 如有需要,将 bean 注册为一次性的,以供 beanFactory 在关闭时调用销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// ...
return exposedObject;
}
-
-createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
-
-- 工厂方法
-- 构造器方法
-- 有参
-- 无参
-
-
-
-populateBean
为创建出的实例填充属性,包括解析当前 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
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// ...
// 给 InstantiationAwareBeanPostProcessors 一个机会,
// 在设置 bean 属性前修改 bean 状态,可用于自定义的字段注入
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 是否继续填充属性的流程
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否存在 InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 后置处理 PropertyValues
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 将属性应用到 bean 上(常规情况下,前面的处理都用不上)
applyPropertyValues(beanName, mbd, bw, pvs);
}
-
-initializeBean
在填充完属性后,实例就可以进行初始化工作:
-
-- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息
-- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
-- invokeInitMethods,调用初始化方法
-- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
-
-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
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 处理 Aware 接口的相应方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 应用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
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()) {
// 应用 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
-
-处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
-1
2
3
4
5
6
7
8
9
10
11
12
13
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
-
-调用初始化方法
-- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法
-- 如果自定义 init 方法且满足调用条件,同样进行调用
-
-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
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 是否实现 InitializingBean 接口,是的话调用 afterPropertiesSet 方法
// 给 bean 一个感知属性已设置并做出反应的机会
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean
&& (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 如果存在自定义的 init 方法且方法名称不是 afterPropertiesSet,判断是否调用
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null
&& !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
-
-BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
-
-- 获取 Processor 列表
-- 判断 Processor 类型是否是当前需要的
-- 对 bean 进行处理
-
-1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
-
-再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
-1
2
3
4
5
6
7
8
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
-
-在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
-
-- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。
-- Bean 自身的初始化。
-
-在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -392,7 +232,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Spring Bean 加载过程
+
+
+
+
+
+
+
+
+
+ Spring Bean 生命周期
+
+获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
+1
2
3
4
public Object getBean(String name) throws BeansException {
// 具体工作由 doGetBean 完成
return doGetBean(name, null, null, false);
}
+
+deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
+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
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换名称:去除 FactoryBean 的前缀 &,将别名转换为规范名称
final String beanName = transformedBeanName(name);
Object bean;
// 检查单例缓存中是否已存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
// 如果已存在,直接返回该实例或者使用该实例(FactoryBean)创建并返回对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果当前 Bean 是一个正在创建中的 prototype 类型,表明可能发生循环引用
// 注意:Spring 并未解决 prototype 类型的循环引用问题,要抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果当前 beanFactory 没有 bean 定义,去 parent beanFactory 中查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 标记为至少创建过一次
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保 bean 依赖的 bean(构造器参数) 都已实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 注意:Spring 并未解决构造器方法中的循环引用问题,要抛异常
}
// 注册依赖关系,确保先销毁被依赖的 bean
registerDependentBean(dep, beanName);
// 递归,获取依赖的 bean
getBean(dep);
}
}
}
if (mbd.isSingleton()) {
// 如果是单例类型(绝大多数都是此类型)
// 再次从缓存中获取,如果仍不存在,则使用传入的 ObjectFactory 创建
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>(
{
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);
}
else if (mbd.isPrototype()) {
// 如果是原型类型,每次都新创建一个
// ...
}
else {
// 如果是其他 scope 类型
// ...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
+
+getSingleton
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 加锁
synchronized (this.singletonObjects) {
// 再次从缓存中获取(和调用前从缓存中获取构成双重校验)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
// 如果正在销毁单例,则抛异常
// 注意:不要在销毁方法中调用获取 bean 方法
}
// 创建前,先注册到正在创建中的集合
// 在出现循环引用时,第二次进入 doGetBean,用此作为判断标志
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// ...
try {
// 使用传入的单例工厂创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 如果异常的出现是因为 bean 被创建了,就忽略异常,否则抛出异常
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
// ...
}
finally {
// ...
// 创建后,从正在创建中集合移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加单例到缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
+
+创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// ...
try {
// 给 Bean 后置处理器一个返回代理的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...
// 常规的创建 Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
+
+doCreateBean
常规的创建 Bean 的具体工作是由 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
39
40
41
42
43
44
45
46
47
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 使用相应的策略创建 bean 实例,例如通过工厂方法或者有参、无参构造器方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// ...
// 使用 ObjectFactory 封装实例并缓存,以解决循环引用问题
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
// 填充属性(包括解析依赖的 bean)
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
// ...
// 如有需要,将 bean 注册为一次性的,以供 beanFactory 在关闭时调用销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// ...
return exposedObject;
}
+
+createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
+
+- 工厂方法
+- 构造器方法
+- 有参
+- 无参
+
+
+
+populateBean
为创建出的实例填充属性,包括解析当前 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
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// ...
// 给 InstantiationAwareBeanPostProcessors 一个机会,
// 在设置 bean 属性前修改 bean 状态,可用于自定义的字段注入
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 是否继续填充属性的流程
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否存在 InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 后置处理 PropertyValues
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 将属性应用到 bean 上(常规情况下,前面的处理都用不上)
applyPropertyValues(beanName, mbd, bw, pvs);
}
+
+initializeBean
在填充完属性后,实例就可以进行初始化工作:
+
+- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息
+- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
+- invokeInitMethods,调用初始化方法
+- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
+
+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
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 处理 Aware 接口的相应方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 应用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
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()) {
// 应用 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
+
+处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
+1
2
3
4
5
6
7
8
9
10
11
12
13
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
+
+调用初始化方法
+- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法
+- 如果自定义 init 方法且满足调用条件,同样进行调用
+
+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
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 是否实现 InitializingBean 接口,是的话调用 afterPropertiesSet 方法
// 给 bean 一个感知属性已设置并做出反应的机会
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean
&& (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 如果存在自定义的 init 方法且方法名称不是 afterPropertiesSet,判断是否调用
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null
&& !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
+
+BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
+
+- 获取 Processor 列表
+- 判断 Processor 类型是否是当前需要的
+- 对 bean 进行处理
+
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
+
+再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
+1
2
3
4
5
6
7
8
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
+
+在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
+
+- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。
+- Bean 自身的初始化。
+
+在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -1701,6 +1541,166 @@
-
+
@@ -1580,7 +1420,7 @@
-
+
@@ -1380,7 +1220,7 @@
-
+
@@ -1147,7 +987,7 @@
-
+
@@ -714,7 +554,7 @@
-
+
@@ -546,7 +386,7 @@
+
+
+
+
+
+
+
@@ -1742,7 +1742,7 @@
Moralok
-
+
diff --git a/leancloud_counter_security_urls.json b/leancloud_counter_security_urls.json
index 881386d7..3857eb32 100644
--- a/leancloud_counter_security_urls.json
+++ b/leancloud_counter_security_urls.json
@@ -1 +1 @@
-[{"title":"在 Ubuntu 上安装 Clash","url":"/2023/05/27/how-to-install-clash-on-ubuntu/"},{"title":"Docker 常用命令列表","url":"/2020/08/19/docker-frequently-used-commands/"},{"title":"在 iOS 和 macOS 上安装 OpenVPN 客户端","url":"/2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/"},{"title":"在 Windows 10 上安装 OpenVPN 服务器","url":"/2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/"},{"title":"使用 OpenVPN 访问家庭内网","url":"/2023/06/07/how-to-use-OpenVPN-to-access-home-network/"},{"title":"Ubuntu server 20.04 安装后没有分配全部磁盘空间","url":"/2023/06/24/Ubuntu-server-20-04-not-all-disk-space-was-allocated-after-installation/"},{"title":"如何使用 SSH 连接 Github 和服务器","url":"/2023/06/28/how-to-use-ssh-to-connect-github-and-server/"},{"title":"Tmux 常用命令和快捷键","url":"/2023/06/29/tmux-frequently-used-commands/"},{"title":"如何为终端、docker 和容器设置代理","url":"/2023/06/13/how-to-configure-proxy-for-terminal-docker-and-container/"},{"title":"如何在 Ubuntu 20.04 上安装 Minikube","url":"/2023/06/23/how-to-install-Minikube-on-Ubuntu-20-04/"},{"title":"JVM GC 的测试和分析","url":"/2023/11/01/testing-and-analysis-of-jvm-gc/"},{"title":"字符串常量池的测试和分析","url":"/2023/11/03/testing-and-analysis-of-StringTable/"},{"title":"Spring Bean 加载过程","url":"/2023/11/17/how-does-Spring-load-beans/"},{"title":"关于 Java 字节码指令的一些例子分析","url":"/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/"},{"title":"基于 Redis 的分布式锁的简单实现","url":"/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/"},{"title":"Java 类加载器源码分析","url":"/2023/07/13/Java-class-loader-source-code-analysis/"},{"title":"JVM 内存区域的测试和分析","url":"/2023/11/04/testing-and-analysis-of-jvm-memory-area/"},{"title":"Java 垃圾收集","url":"/2023/11/07/garbage-collection-in-Java/"}]
\ No newline at end of file
+[{"title":"在 Ubuntu 上安装 Clash","url":"/2023/05/27/how-to-install-clash-on-ubuntu/"},{"title":"在 iOS 和 macOS 上安装 OpenVPN 客户端","url":"/2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/"},{"title":"在 Windows 10 上安装 OpenVPN 服务器","url":"/2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/"},{"title":"使用 OpenVPN 访问家庭内网","url":"/2023/06/07/how-to-use-OpenVPN-to-access-home-network/"},{"title":"如何为终端、docker 和容器设置代理","url":"/2023/06/13/how-to-configure-proxy-for-terminal-docker-and-container/"},{"title":"Docker 常用命令列表","url":"/2020/08/19/docker-frequently-used-commands/"},{"title":"Ubuntu server 20.04 安装后没有分配全部磁盘空间","url":"/2023/06/24/Ubuntu-server-20-04-not-all-disk-space-was-allocated-after-installation/"},{"title":"Tmux 常用命令和快捷键","url":"/2023/06/29/tmux-frequently-used-commands/"},{"title":"如何使用 SSH 连接 Github 和服务器","url":"/2023/06/28/how-to-use-ssh-to-connect-github-and-server/"},{"title":"如何在 Ubuntu 20.04 上安装 Minikube","url":"/2023/06/23/how-to-install-Minikube-on-Ubuntu-20-04/"},{"title":"Spring Bean 加载过程","url":"/2023/08/10/how-does-Spring-load-beans/"},{"title":"JVM GC 的测试和分析","url":"/2023/11/01/testing-and-analysis-of-jvm-gc/"},{"title":"字符串常量池的测试和分析","url":"/2023/11/03/testing-and-analysis-of-StringTable/"},{"title":"Java 类加载器源码分析","url":"/2023/07/13/Java-class-loader-source-code-analysis/"},{"title":"关于 Java 字节码指令的一些例子分析","url":"/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/"},{"title":"基于 Redis 的分布式锁的简单实现","url":"/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/"},{"title":"JVM 内存区域的测试和分析","url":"/2023/11/04/testing-and-analysis-of-jvm-memory-area/"},{"title":"Java 垃圾收集","url":"/2023/11/07/garbage-collection-in-Java/"}]
\ No newline at end of file
diff --git a/page/2/index.html b/page/2/index.html
index 36d9d6ec..ab4a4a4e 100644
--- a/page/2/index.html
+++ b/page/2/index.html
@@ -158,7 +158,7 @@
-
+
@@ -2182,7 +2182,7 @@
-
+
@@ -2028,7 +2028,7 @@
@@ -232,7 +232,7 @@
proxy
+
+ 在 iOS 和 macOS 上安装 OpenVPN 客户端
+ /2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/
+ 安装 OpenVPN Connect
-
+
diff --git a/search.xml b/search.xml
index caf717a6..7947b806 100644
--- a/search.xml
+++ b/search.xml
@@ -45,6 +45,176 @@
-
+
@@ -1151,7 +1151,7 @@
-
+
@@ -1018,7 +1018,7 @@
-
+
@@ -897,7 +897,7 @@
-
+
@@ -781,7 +781,7 @@
-
+
@@ -633,7 +633,7 @@
-
+
@@ -493,7 +493,7 @@
-
+
@@ -343,7 +343,7 @@ macOS 访问官网下载。
iOS 访问 AppStore,需要登录外区 Apple ID。
+配置 OpenVPN Connect
客户端提供了两种方式导入配置文件,一是通过 URL,建议 URL 仅限在私有网络内访问,二是通过其他方式例如邮件,下载为本地文件再导入。
+配置文件的组织方式又分为两种形式,一种是将 CA 根证书 ca.crt,客户端证书 client.crt,客户端密钥 client.key 的内容复制粘贴到 client.ovpn 中,形成一个联合配置文件;另一种是使用 openssl 将 CA 根证书 ca.crt,客户端证书 client.crt,客户端密钥 client.key 转换为 PKCS#12 文件,先后导入 client.ovpn12 和 client.ovpn。
+单一 client.ovpn
从目录 C:\Program Files\OpenVPN\sample-config
复制客户端配置文件模板 client.ovpn,修改以下配置:
+remote your-server 1194
;ca ca.crt
;cert client.crt
;key client.key
;tls-auth ta.key 1
<ca>
-----BEGIN CERTIFICATE-----
paste contents of ca.crt
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
paste contents of client.crt
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
paste contents of client.key
-----END PRIVATE KEY-----
</key>
+将 remote your-server 1194
中的地址和端口替换成你的 OpenVPN server 的地址和端口。将 ca ca.crt
, cert client.crt
, key client.key
, tls-auth ta.key 1
注释掉,将各自文件中的内容以上述类 XML 的形式粘贴到 client.ovpn 中。
+将修改好的客户端配置文件导入到客户端中即可。
+client.ovpn + client.opvn12
使用 openssl 命令将客户端的证书和私钥文件转换为 PKCS#12 形式的文件。该命令会提示 Enter Export Password
,可以为空,但为了安全建议设置密码。
+openssl pkcs12 -export -in cert -inkey key -certfile ca -name MyClient -out client.ovpn12
+由于在 iOS 中导入 PKCS#12 文件到 Keychain 中时只导入了客户端证书和密钥,CA 根证书并没有导入,client.ovpn 文件中必须要保留 CA 根证书的配置。
既可以用传统的引用文件的方式:
+ca ca.crt
+也可以用类 XML 的形式粘贴 ca.crt 内容到 client.ovpn 中:
+<ca>
paste contents of ca.crt here
</ca>
+先导入 client.ovpn12(需要输入转换时的密码),再导入 client.ovpn。
+
+但是我失败了……导入 client.ovpn12 时密码一直错误,搜索到类似的案例,但是没有找到解决方案。不确定是不是 openssl 版本引起的。
+
+路由器 NAT
在路由器管理后台的 NAT 设置功能里,配置好对外端口号和 Windows 10 主机上 OpenVPN 端口号的映射关系。
+参考链接
iOS 使用 OpenVPN 的 FAQ
如何通过 iOS Keychain 使用客户端证书和密钥
如何配置 iOS OpenVPN 客户端的证书认证
+]]>
+
+ openvpn
+
+
+
+ 在 Windows 10 上安装 OpenVPN 服务器
+ /2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/
+ 安装 OpenVPN server
@@ -191,166 +191,6 @@
@@ -203,26 +203,6 @@
@@ -203,26 +203,6 @@
-
+
@@ -359,9 +359,6 @@ 从 OpenVPN 社区 下载 Windows 64-bit MSI installer。本次安装的版本为 OpenVPN 2.6.4。
+
+注意事项:在选择安装类型时选择 Customize 而不要选择 Install Now。额外勾选 OpenVPN -> OpenVPN Service -> Entire feature will be installed on local hard drive 和 OpenSSL Utilities -> EasyRSA 3 Certificate Management Scripts -> Entire feature will be installed on local hard drive。
+
+安装完毕后,会弹出一条消息提示未找到可读的连接配置文件,暂时忽略。
此时在 控制面板\网络和 Internet\网络连接 中可以看到创建了两个新的网络适配器 OpenVPN TAP-Windows6 和 OpenVPN Wintun。
+配置 OpenVPN server
打开 Windows 10 终端程序。
进入 OpenVPN 默认安装目录中的 easy-rsa 目录。
+cd 'C:\Program Files\OpenVPN\easy-rsa'
+执行命令进入 Easy-RSA 3 Shell
+.\EasyRSA-Start.bat
+初始化公钥基础设施目录 pki
+./easyrsa init-pki
+构建证书颁发机构(CA)密钥,CA 根证书文件将在后续用于对其他证书和密钥进行签名。该命令要求输入 Common Name,输入主机名即可。创建的 ca.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki
中,ca.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
+./easyrsa build-ca nopass
+构建服务器证书和密钥。创建的 server.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\issued
中,server.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
+./easyrsa build-server-full server nopass
+构建客户端证书和密钥。创建的 client.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\issued
中,client.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
+./easyrsa build-client-full client nopass
+生成 Diffie-Hellman 参数
+./easyrsa gen-dh
+从目录 C:\Program Files\OpenVPN\sample-config
复制服务端配置文件模板 server.ovpn 到目录 C:\Program Files\OpenVPN\config
中,修改以下配置:
+port 1194
dh dh.pem
duplicate-cn
;tls-auth ta.key 0
+端口号按需修改,默认为1194,需要保证 OpenVPN 的网络流量可以通过防火墙,设置 Windows 10 Defender 允许 OpenVPN 通过即可。dh2048.pem 修改为生成的文件名 dh.pem。取消注释 duplicate-cn,让多个客户端使用同一个客户端证书。注释掉 tls-auth ta.key 0。复制 ca.crt,dh.pem,server.crt 和 server.key 到目录 C:\Program Files\OpenVPN\config 中。
+启动与连接
启动 OpenVPN,点击连接,系统提示分配 IP 10.8.0.1。按配置,每次 OpenVPN server 都将为自己分配 10.8.0.1。
+参考链接
openvpn安装配置说明(windows系统)
如何在Windows 10上安装和配置OpenVPN
+]]>
+
+ openvpn
+
+
+
+ 使用 OpenVPN 访问家庭内网
+ /2023/06/07/how-to-use-OpenVPN-to-access-home-network/
+ 网络概况
diff --git a/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html b/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html
index 9bff8d7e..f765d3b9 100644
--- a/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html
+++ b/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html
@@ -33,7 +33,7 @@
-
+
@@ -170,7 +170,7 @@
@@ -245,7 +245,7 @@
-
+
@@ -355,7 +355,7 @@ 宽带是电信宽带,分配了动态的公网 IP。
光猫使用桥接模式,通过路由器拨号上网(PPPoE),路由器局域网为 192.168.3.0/24。
一台 Windows 10 主机,在路由器局域网上的 IP 192.168.3.120。。
Windows 10 主机上运行 Vmware 虚拟机,网络采用 NAT 模式。子网为 192.168.46.0/24。运行了 Linux 主机,IP 192.168.46.128。Windows 10 主机在子网中的 IP 为 192.168.3.1。
+
diff --git a/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/index.html b/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/index.html
index 66a39560..04068448 100644
--- a/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/index.html
+++ b/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/index.html
@@ -28,9 +28,9 @@
-
+
-
+
@@ -165,7 +165,7 @@
@@ -240,7 +240,7 @@
-
+
@@ -626,7 +626,7 @@
diff --git a/2023/11/07/garbage-collection-in-Java/index.html b/2023/11/07/garbage-collection-in-Java/index.html
index 48c53b1f..1d18ff48 100644
--- a/2023/11/07/garbage-collection-in-Java/index.html
+++ b/2023/11/07/garbage-collection-in-Java/index.html
@@ -34,9 +34,9 @@
-
+
-
+
@@ -171,7 +171,7 @@
@@ -246,7 +246,7 @@
-
+
@@ -424,7 +424,7 @@
diff --git a/2023/11/04/testing-and-analysis-of-jvm-memory-area/index.html b/2023/11/04/testing-and-analysis-of-jvm-memory-area/index.html
index 2d09282c..f23b8c0f 100644
--- a/2023/11/04/testing-and-analysis-of-jvm-memory-area/index.html
+++ b/2023/11/04/testing-and-analysis-of-jvm-memory-area/index.html
@@ -32,9 +32,9 @@
-
+
-
+
@@ -169,7 +169,7 @@
@@ -244,7 +244,7 @@
-
+
@@ -390,7 +390,7 @@
@@ -243,7 +243,7 @@
@@ -355,8 +355,8 @@
-
- Spring Bean 加载过程
-
diff --git a/archives/2020/08/index.html b/archives/2020/08/index.html
index 5cb2fa4a..9a8aec9a 100644
--- a/archives/2020/08/index.html
+++ b/archives/2020/08/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2020/index.html b/archives/2020/index.html
index 4c74ba98..18e0f275 100644
--- a/archives/2020/index.html
+++ b/archives/2020/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/05/index.html b/archives/2023/05/index.html
index 539bcf0e..183b92da 100644
--- a/archives/2023/05/index.html
+++ b/archives/2023/05/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/06/index.html b/archives/2023/06/index.html
index be634e2c..5272063f 100644
--- a/archives/2023/06/index.html
+++ b/archives/2023/06/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/07/index.html b/archives/2023/07/index.html
index 7f1c535f..1cb43f2f 100644
--- a/archives/2023/07/index.html
+++ b/archives/2023/07/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/tags/Java/index.html b/archives/2023/08/index.html
similarity index 70%
rename from tags/Java/index.html
rename to archives/2023/08/index.html
index 94638b7d..4aa36998 100644
--- a/tags/Java/index.html
+++ b/archives/2023/08/index.html
@@ -22,7 +22,7 @@
-
+
@@ -30,14 +30,14 @@
-
+
-
+
-标签: Java | Moralok
+归档 | Moralok
@@ -68,7 +68,7 @@
- Moralok
+ Moralok
@@ -158,7 +158,7 @@
@@ -186,7 +186,7 @@
-
+
@@ -195,9 +195,7 @@
- Java
- 标签
-
+ 嗯..! 目前共计 18 篇日志。 继续努力。
@@ -209,15 +207,15 @@ Java
@@ -225,105 +223,6 @@ Java
-
-
-
-
- Java 垃圾收集
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 字符串常量池的测试和分析
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/archives/2023/11/index.html b/archives/2023/11/index.html
index 38cea205..ece70fec 100644
--- a/archives/2023/11/index.html
+++ b/archives/2023/11/index.html
@@ -158,7 +158,7 @@ Moralok
@@ -203,26 +203,6 @@ Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Spring Bean 加载过程
-
-
-
-
-
-
-
-
-
- Spring Bean 生命周期
-
-获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
-1
2
3
4
public Object getBean(String name) throws BeansException {
// 具体工作由 doGetBean 完成
return doGetBean(name, null, null, false);
}
-
-deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
-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
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换名称:去除 FactoryBean 的前缀 &,将别名转换为规范名称
final String beanName = transformedBeanName(name);
Object bean;
// 检查单例缓存中是否已存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
// 如果已存在,直接返回该实例或者使用该实例(FactoryBean)创建并返回对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果当前 Bean 是一个正在创建中的 prototype 类型,表明可能发生循环引用
// 注意:Spring 并未解决 prototype 类型的循环引用问题,要抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果当前 beanFactory 没有 bean 定义,去 parent beanFactory 中查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 标记为至少创建过一次
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保 bean 依赖的 bean(构造器参数) 都已实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 注意:Spring 并未解决构造器方法中的循环引用问题,要抛异常
}
// 注册依赖关系,确保先销毁被依赖的 bean
registerDependentBean(dep, beanName);
// 递归,获取依赖的 bean
getBean(dep);
}
}
}
if (mbd.isSingleton()) {
// 如果是单例类型(绝大多数都是此类型)
// 再次从缓存中获取,如果仍不存在,则使用传入的 ObjectFactory 创建
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>(
{
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);
}
else if (mbd.isPrototype()) {
// 如果是原型类型,每次都新创建一个
// ...
}
else {
// 如果是其他 scope 类型
// ...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
-
-getSingleton
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 加锁
synchronized (this.singletonObjects) {
// 再次从缓存中获取(和调用前从缓存中获取构成双重校验)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
// 如果正在销毁单例,则抛异常
// 注意:不要在销毁方法中调用获取 bean 方法
}
// 创建前,先注册到正在创建中的集合
// 在出现循环引用时,第二次进入 doGetBean,用此作为判断标志
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// ...
try {
// 使用传入的单例工厂创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 如果异常的出现是因为 bean 被创建了,就忽略异常,否则抛出异常
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
// ...
}
finally {
// ...
// 创建后,从正在创建中集合移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加单例到缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
-
-创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
-1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// ...
try {
// 给 Bean 后置处理器一个返回代理的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...
// 常规的创建 Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
-
-doCreateBean
常规的创建 Bean 的具体工作是由 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
39
40
41
42
43
44
45
46
47
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 使用相应的策略创建 bean 实例,例如通过工厂方法或者有参、无参构造器方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// ...
// 使用 ObjectFactory 封装实例并缓存,以解决循环引用问题
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
// 填充属性(包括解析依赖的 bean)
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
// ...
// 如有需要,将 bean 注册为一次性的,以供 beanFactory 在关闭时调用销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// ...
return exposedObject;
}
-
-createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
-
-- 工厂方法
-- 构造器方法
-- 有参
-- 无参
-
-
-
-populateBean
为创建出的实例填充属性,包括解析当前 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
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// ...
// 给 InstantiationAwareBeanPostProcessors 一个机会,
// 在设置 bean 属性前修改 bean 状态,可用于自定义的字段注入
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 是否继续填充属性的流程
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否存在 InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 后置处理 PropertyValues
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 将属性应用到 bean 上(常规情况下,前面的处理都用不上)
applyPropertyValues(beanName, mbd, bw, pvs);
}
-
-initializeBean
在填充完属性后,实例就可以进行初始化工作:
-
-- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息
-- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
-- invokeInitMethods,调用初始化方法
-- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
-
-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
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 处理 Aware 接口的相应方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 应用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
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()) {
// 应用 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
-
-处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
-1
2
3
4
5
6
7
8
9
10
11
12
13
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
-
-调用初始化方法
-- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法
-- 如果自定义 init 方法且满足调用条件,同样进行调用
-
-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
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 是否实现 InitializingBean 接口,是的话调用 afterPropertiesSet 方法
// 给 bean 一个感知属性已设置并做出反应的机会
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean
&& (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 如果存在自定义的 init 方法且方法名称不是 afterPropertiesSet,判断是否调用
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null
&& !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
-
-BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
-
-- 获取 Processor 列表
-- 判断 Processor 类型是否是当前需要的
-- 对 bean 进行处理
-
-1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
-
-再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
-1
2
3
4
5
6
7
8
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
-
-在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
-
-- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。
-- Bean 自身的初始化。
-
-在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -392,7 +232,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Spring Bean 加载过程
+
+
+
+
+
+
+
+
+
+ Spring Bean 生命周期
+
+获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
+1
2
3
4
public Object getBean(String name) throws BeansException {
// 具体工作由 doGetBean 完成
return doGetBean(name, null, null, false);
}
+
+deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
+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
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换名称:去除 FactoryBean 的前缀 &,将别名转换为规范名称
final String beanName = transformedBeanName(name);
Object bean;
// 检查单例缓存中是否已存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
// 如果已存在,直接返回该实例或者使用该实例(FactoryBean)创建并返回对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果当前 Bean 是一个正在创建中的 prototype 类型,表明可能发生循环引用
// 注意:Spring 并未解决 prototype 类型的循环引用问题,要抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果当前 beanFactory 没有 bean 定义,去 parent beanFactory 中查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 标记为至少创建过一次
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保 bean 依赖的 bean(构造器参数) 都已实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 注意:Spring 并未解决构造器方法中的循环引用问题,要抛异常
}
// 注册依赖关系,确保先销毁被依赖的 bean
registerDependentBean(dep, beanName);
// 递归,获取依赖的 bean
getBean(dep);
}
}
}
if (mbd.isSingleton()) {
// 如果是单例类型(绝大多数都是此类型)
// 再次从缓存中获取,如果仍不存在,则使用传入的 ObjectFactory 创建
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>(
{
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);
}
else if (mbd.isPrototype()) {
// 如果是原型类型,每次都新创建一个
// ...
}
else {
// 如果是其他 scope 类型
// ...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
+
+getSingleton
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 加锁
synchronized (this.singletonObjects) {
// 再次从缓存中获取(和调用前从缓存中获取构成双重校验)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
// 如果正在销毁单例,则抛异常
// 注意:不要在销毁方法中调用获取 bean 方法
}
// 创建前,先注册到正在创建中的集合
// 在出现循环引用时,第二次进入 doGetBean,用此作为判断标志
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// ...
try {
// 使用传入的单例工厂创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 如果异常的出现是因为 bean 被创建了,就忽略异常,否则抛出异常
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
// ...
}
finally {
// ...
// 创建后,从正在创建中集合移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加单例到缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
+
+创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// ...
try {
// 给 Bean 后置处理器一个返回代理的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...
// 常规的创建 Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
+
+doCreateBean
常规的创建 Bean 的具体工作是由 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
39
40
41
42
43
44
45
46
47
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 使用相应的策略创建 bean 实例,例如通过工厂方法或者有参、无参构造器方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// ...
// 使用 ObjectFactory 封装实例并缓存,以解决循环引用问题
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
// 填充属性(包括解析依赖的 bean)
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
// ...
// 如有需要,将 bean 注册为一次性的,以供 beanFactory 在关闭时调用销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// ...
return exposedObject;
}
+
+createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
+
+- 工厂方法
+- 构造器方法
+- 有参
+- 无参
+
+
+
+populateBean
为创建出的实例填充属性,包括解析当前 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
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// ...
// 给 InstantiationAwareBeanPostProcessors 一个机会,
// 在设置 bean 属性前修改 bean 状态,可用于自定义的字段注入
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 是否继续填充属性的流程
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否存在 InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 后置处理 PropertyValues
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 将属性应用到 bean 上(常规情况下,前面的处理都用不上)
applyPropertyValues(beanName, mbd, bw, pvs);
}
+
+initializeBean
在填充完属性后,实例就可以进行初始化工作:
+
+- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息
+- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
+- invokeInitMethods,调用初始化方法
+- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
+
+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
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 处理 Aware 接口的相应方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 应用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
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()) {
// 应用 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
+
+处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
+1
2
3
4
5
6
7
8
9
10
11
12
13
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
+
+调用初始化方法
+- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法
+- 如果自定义 init 方法且满足调用条件,同样进行调用
+
+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
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 是否实现 InitializingBean 接口,是的话调用 afterPropertiesSet 方法
// 给 bean 一个感知属性已设置并做出反应的机会
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean
&& (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 如果存在自定义的 init 方法且方法名称不是 afterPropertiesSet,判断是否调用
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null
&& !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
+
+BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
+
+- 获取 Processor 列表
+- 判断 Processor 类型是否是当前需要的
+- 对 bean 进行处理
+
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
+
+再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
+1
2
3
4
5
6
7
8
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
+
+在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
+
+- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。
+- Bean 自身的初始化。
+
+在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -1701,6 +1541,166 @@
-
+
@@ -1580,7 +1420,7 @@
-
+
@@ -1380,7 +1220,7 @@
-
+
@@ -1147,7 +987,7 @@
-
+
@@ -714,7 +554,7 @@
-
+
@@ -546,7 +386,7 @@
+
+
+
+
+
+
+
@@ -1742,7 +1742,7 @@
Moralok
-
+
diff --git a/leancloud_counter_security_urls.json b/leancloud_counter_security_urls.json
index 881386d7..3857eb32 100644
--- a/leancloud_counter_security_urls.json
+++ b/leancloud_counter_security_urls.json
@@ -1 +1 @@
-[{"title":"在 Ubuntu 上安装 Clash","url":"/2023/05/27/how-to-install-clash-on-ubuntu/"},{"title":"Docker 常用命令列表","url":"/2020/08/19/docker-frequently-used-commands/"},{"title":"在 iOS 和 macOS 上安装 OpenVPN 客户端","url":"/2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/"},{"title":"在 Windows 10 上安装 OpenVPN 服务器","url":"/2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/"},{"title":"使用 OpenVPN 访问家庭内网","url":"/2023/06/07/how-to-use-OpenVPN-to-access-home-network/"},{"title":"Ubuntu server 20.04 安装后没有分配全部磁盘空间","url":"/2023/06/24/Ubuntu-server-20-04-not-all-disk-space-was-allocated-after-installation/"},{"title":"如何使用 SSH 连接 Github 和服务器","url":"/2023/06/28/how-to-use-ssh-to-connect-github-and-server/"},{"title":"Tmux 常用命令和快捷键","url":"/2023/06/29/tmux-frequently-used-commands/"},{"title":"如何为终端、docker 和容器设置代理","url":"/2023/06/13/how-to-configure-proxy-for-terminal-docker-and-container/"},{"title":"如何在 Ubuntu 20.04 上安装 Minikube","url":"/2023/06/23/how-to-install-Minikube-on-Ubuntu-20-04/"},{"title":"JVM GC 的测试和分析","url":"/2023/11/01/testing-and-analysis-of-jvm-gc/"},{"title":"字符串常量池的测试和分析","url":"/2023/11/03/testing-and-analysis-of-StringTable/"},{"title":"Spring Bean 加载过程","url":"/2023/11/17/how-does-Spring-load-beans/"},{"title":"关于 Java 字节码指令的一些例子分析","url":"/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/"},{"title":"基于 Redis 的分布式锁的简单实现","url":"/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/"},{"title":"Java 类加载器源码分析","url":"/2023/07/13/Java-class-loader-source-code-analysis/"},{"title":"JVM 内存区域的测试和分析","url":"/2023/11/04/testing-and-analysis-of-jvm-memory-area/"},{"title":"Java 垃圾收集","url":"/2023/11/07/garbage-collection-in-Java/"}]
\ No newline at end of file
+[{"title":"在 Ubuntu 上安装 Clash","url":"/2023/05/27/how-to-install-clash-on-ubuntu/"},{"title":"在 iOS 和 macOS 上安装 OpenVPN 客户端","url":"/2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/"},{"title":"在 Windows 10 上安装 OpenVPN 服务器","url":"/2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/"},{"title":"使用 OpenVPN 访问家庭内网","url":"/2023/06/07/how-to-use-OpenVPN-to-access-home-network/"},{"title":"如何为终端、docker 和容器设置代理","url":"/2023/06/13/how-to-configure-proxy-for-terminal-docker-and-container/"},{"title":"Docker 常用命令列表","url":"/2020/08/19/docker-frequently-used-commands/"},{"title":"Ubuntu server 20.04 安装后没有分配全部磁盘空间","url":"/2023/06/24/Ubuntu-server-20-04-not-all-disk-space-was-allocated-after-installation/"},{"title":"Tmux 常用命令和快捷键","url":"/2023/06/29/tmux-frequently-used-commands/"},{"title":"如何使用 SSH 连接 Github 和服务器","url":"/2023/06/28/how-to-use-ssh-to-connect-github-and-server/"},{"title":"如何在 Ubuntu 20.04 上安装 Minikube","url":"/2023/06/23/how-to-install-Minikube-on-Ubuntu-20-04/"},{"title":"Spring Bean 加载过程","url":"/2023/08/10/how-does-Spring-load-beans/"},{"title":"JVM GC 的测试和分析","url":"/2023/11/01/testing-and-analysis-of-jvm-gc/"},{"title":"字符串常量池的测试和分析","url":"/2023/11/03/testing-and-analysis-of-StringTable/"},{"title":"Java 类加载器源码分析","url":"/2023/07/13/Java-class-loader-source-code-analysis/"},{"title":"关于 Java 字节码指令的一些例子分析","url":"/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/"},{"title":"基于 Redis 的分布式锁的简单实现","url":"/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/"},{"title":"JVM 内存区域的测试和分析","url":"/2023/11/04/testing-and-analysis-of-jvm-memory-area/"},{"title":"Java 垃圾收集","url":"/2023/11/07/garbage-collection-in-Java/"}]
\ No newline at end of file
diff --git a/page/2/index.html b/page/2/index.html
index 36d9d6ec..ab4a4a4e 100644
--- a/page/2/index.html
+++ b/page/2/index.html
@@ -158,7 +158,7 @@
-
+
@@ -2182,7 +2182,7 @@
-
+
@@ -2028,7 +2028,7 @@
@@ -232,7 +232,7 @@
proxy
+
+ 在 iOS 和 macOS 上安装 OpenVPN 客户端
+ /2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/
+ 安装 OpenVPN Connect
-
+
diff --git a/search.xml b/search.xml
index caf717a6..7947b806 100644
--- a/search.xml
+++ b/search.xml
@@ -45,6 +45,176 @@
-
+
@@ -1151,7 +1151,7 @@
-
+
@@ -1018,7 +1018,7 @@
-
+
@@ -897,7 +897,7 @@
-
+
@@ -781,7 +781,7 @@
-
+
@@ -633,7 +633,7 @@
-
+
@@ -493,7 +493,7 @@
-
+
@@ -343,7 +343,7 @@ macOS 访问官网下载。
iOS 访问 AppStore,需要登录外区 Apple ID。
+配置 OpenVPN Connect
客户端提供了两种方式导入配置文件,一是通过 URL,建议 URL 仅限在私有网络内访问,二是通过其他方式例如邮件,下载为本地文件再导入。
+配置文件的组织方式又分为两种形式,一种是将 CA 根证书 ca.crt,客户端证书 client.crt,客户端密钥 client.key 的内容复制粘贴到 client.ovpn 中,形成一个联合配置文件;另一种是使用 openssl 将 CA 根证书 ca.crt,客户端证书 client.crt,客户端密钥 client.key 转换为 PKCS#12 文件,先后导入 client.ovpn12 和 client.ovpn。
+单一 client.ovpn
从目录 C:\Program Files\OpenVPN\sample-config
复制客户端配置文件模板 client.ovpn,修改以下配置:
+remote your-server 1194
;ca ca.crt
;cert client.crt
;key client.key
;tls-auth ta.key 1
<ca>
-----BEGIN CERTIFICATE-----
paste contents of ca.crt
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
paste contents of client.crt
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
paste contents of client.key
-----END PRIVATE KEY-----
</key>
+将 remote your-server 1194
中的地址和端口替换成你的 OpenVPN server 的地址和端口。将 ca ca.crt
, cert client.crt
, key client.key
, tls-auth ta.key 1
注释掉,将各自文件中的内容以上述类 XML 的形式粘贴到 client.ovpn 中。
+将修改好的客户端配置文件导入到客户端中即可。
+client.ovpn + client.opvn12
使用 openssl 命令将客户端的证书和私钥文件转换为 PKCS#12 形式的文件。该命令会提示 Enter Export Password
,可以为空,但为了安全建议设置密码。
+openssl pkcs12 -export -in cert -inkey key -certfile ca -name MyClient -out client.ovpn12
+由于在 iOS 中导入 PKCS#12 文件到 Keychain 中时只导入了客户端证书和密钥,CA 根证书并没有导入,client.ovpn 文件中必须要保留 CA 根证书的配置。
既可以用传统的引用文件的方式:
+ca ca.crt
+也可以用类 XML 的形式粘贴 ca.crt 内容到 client.ovpn 中:
+<ca>
paste contents of ca.crt here
</ca>
+先导入 client.ovpn12(需要输入转换时的密码),再导入 client.ovpn。
+
+但是我失败了……导入 client.ovpn12 时密码一直错误,搜索到类似的案例,但是没有找到解决方案。不确定是不是 openssl 版本引起的。
+
+路由器 NAT
在路由器管理后台的 NAT 设置功能里,配置好对外端口号和 Windows 10 主机上 OpenVPN 端口号的映射关系。
+参考链接
iOS 使用 OpenVPN 的 FAQ
如何通过 iOS Keychain 使用客户端证书和密钥
如何配置 iOS OpenVPN 客户端的证书认证
+]]>
+
+ openvpn
+
+
+
+ 在 Windows 10 上安装 OpenVPN 服务器
+ /2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/
+ 安装 OpenVPN server
@@ -191,166 +191,6 @@
@@ -203,26 +203,6 @@
@@ -203,26 +203,6 @@
-
+
@@ -359,9 +359,6 @@ 从 OpenVPN 社区 下载 Windows 64-bit MSI installer。本次安装的版本为 OpenVPN 2.6.4。
+
+注意事项:在选择安装类型时选择 Customize 而不要选择 Install Now。额外勾选 OpenVPN -> OpenVPN Service -> Entire feature will be installed on local hard drive 和 OpenSSL Utilities -> EasyRSA 3 Certificate Management Scripts -> Entire feature will be installed on local hard drive。
+
+安装完毕后,会弹出一条消息提示未找到可读的连接配置文件,暂时忽略。
此时在 控制面板\网络和 Internet\网络连接 中可以看到创建了两个新的网络适配器 OpenVPN TAP-Windows6 和 OpenVPN Wintun。
+配置 OpenVPN server
打开 Windows 10 终端程序。
进入 OpenVPN 默认安装目录中的 easy-rsa 目录。
+cd 'C:\Program Files\OpenVPN\easy-rsa'
+执行命令进入 Easy-RSA 3 Shell
+.\EasyRSA-Start.bat
+初始化公钥基础设施目录 pki
+./easyrsa init-pki
+构建证书颁发机构(CA)密钥,CA 根证书文件将在后续用于对其他证书和密钥进行签名。该命令要求输入 Common Name,输入主机名即可。创建的 ca.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki
中,ca.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
+./easyrsa build-ca nopass
+构建服务器证书和密钥。创建的 server.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\issued
中,server.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
+./easyrsa build-server-full server nopass
+构建客户端证书和密钥。创建的 client.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\issued
中,client.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
+./easyrsa build-client-full client nopass
+生成 Diffie-Hellman 参数
+./easyrsa gen-dh
+从目录 C:\Program Files\OpenVPN\sample-config
复制服务端配置文件模板 server.ovpn 到目录 C:\Program Files\OpenVPN\config
中,修改以下配置:
+port 1194
dh dh.pem
duplicate-cn
;tls-auth ta.key 0
+端口号按需修改,默认为1194,需要保证 OpenVPN 的网络流量可以通过防火墙,设置 Windows 10 Defender 允许 OpenVPN 通过即可。dh2048.pem 修改为生成的文件名 dh.pem。取消注释 duplicate-cn,让多个客户端使用同一个客户端证书。注释掉 tls-auth ta.key 0。复制 ca.crt,dh.pem,server.crt 和 server.key 到目录 C:\Program Files\OpenVPN\config 中。
+启动与连接
启动 OpenVPN,点击连接,系统提示分配 IP 10.8.0.1。按配置,每次 OpenVPN server 都将为自己分配 10.8.0.1。
+参考链接
openvpn安装配置说明(windows系统)
如何在Windows 10上安装和配置OpenVPN
+]]>
+
+ openvpn
+
+
+
+ 使用 OpenVPN 访问家庭内网
+ /2023/06/07/how-to-use-OpenVPN-to-access-home-network/
+ 网络概况
diff --git a/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html b/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html
index 9bff8d7e..f765d3b9 100644
--- a/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html
+++ b/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html
@@ -33,7 +33,7 @@
-
+
@@ -170,7 +170,7 @@
@@ -245,7 +245,7 @@
-
+
@@ -355,7 +355,7 @@ 宽带是电信宽带,分配了动态的公网 IP。
光猫使用桥接模式,通过路由器拨号上网(PPPoE),路由器局域网为 192.168.3.0/24。
一台 Windows 10 主机,在路由器局域网上的 IP 192.168.3.120。。
Windows 10 主机上运行 Vmware 虚拟机,网络采用 NAT 模式。子网为 192.168.46.0/24。运行了 Linux 主机,IP 192.168.46.128。Windows 10 主机在子网中的 IP 为 192.168.3.1。
+
diff --git a/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/index.html b/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/index.html
index 66a39560..04068448 100644
--- a/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/index.html
+++ b/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/index.html
@@ -28,9 +28,9 @@
-
+
-
+
@@ -165,7 +165,7 @@
@@ -240,7 +240,7 @@
-
+
@@ -626,7 +626,7 @@
diff --git a/2023/11/07/garbage-collection-in-Java/index.html b/2023/11/07/garbage-collection-in-Java/index.html
index 48c53b1f..1d18ff48 100644
--- a/2023/11/07/garbage-collection-in-Java/index.html
+++ b/2023/11/07/garbage-collection-in-Java/index.html
@@ -34,9 +34,9 @@
-
+
-
+
@@ -171,7 +171,7 @@
@@ -246,7 +246,7 @@
-
+
@@ -424,7 +424,7 @@
diff --git a/2023/11/04/testing-and-analysis-of-jvm-memory-area/index.html b/2023/11/04/testing-and-analysis-of-jvm-memory-area/index.html
index 2d09282c..f23b8c0f 100644
--- a/2023/11/04/testing-and-analysis-of-jvm-memory-area/index.html
+++ b/2023/11/04/testing-and-analysis-of-jvm-memory-area/index.html
@@ -32,9 +32,9 @@
-
+
-
+
@@ -169,7 +169,7 @@
@@ -244,7 +244,7 @@
-
+
@@ -390,7 +390,7 @@
-
- Spring Bean 加载过程
-
diff --git a/archives/2020/08/index.html b/archives/2020/08/index.html
index 5cb2fa4a..9a8aec9a 100644
--- a/archives/2020/08/index.html
+++ b/archives/2020/08/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2020/index.html b/archives/2020/index.html
index 4c74ba98..18e0f275 100644
--- a/archives/2020/index.html
+++ b/archives/2020/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/05/index.html b/archives/2023/05/index.html
index 539bcf0e..183b92da 100644
--- a/archives/2023/05/index.html
+++ b/archives/2023/05/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/06/index.html b/archives/2023/06/index.html
index be634e2c..5272063f 100644
--- a/archives/2023/06/index.html
+++ b/archives/2023/06/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/07/index.html b/archives/2023/07/index.html
index 7f1c535f..1cb43f2f 100644
--- a/archives/2023/07/index.html
+++ b/archives/2023/07/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/tags/Java/index.html b/archives/2023/08/index.html
similarity index 70%
rename from tags/Java/index.html
rename to archives/2023/08/index.html
index 94638b7d..4aa36998 100644
--- a/tags/Java/index.html
+++ b/archives/2023/08/index.html
@@ -22,7 +22,7 @@
-
+
@@ -30,14 +30,14 @@
-
+
-
+
-标签: Java | Moralok
+归档 | Moralok
@@ -68,7 +68,7 @@
- Moralok
+ Moralok
@@ -158,7 +158,7 @@
@@ -186,7 +186,7 @@
-
+
@@ -195,9 +195,7 @@
- Java
- 标签
-
+ 嗯..! 目前共计 18 篇日志。 继续努力。
@@ -209,15 +207,15 @@ Java
@@ -225,105 +223,6 @@ Java
-
-
-
-
- Java 垃圾收集
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 字符串常量池的测试和分析
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/archives/2023/11/index.html b/archives/2023/11/index.html
index 38cea205..ece70fec 100644
--- a/archives/2023/11/index.html
+++ b/archives/2023/11/index.html
@@ -158,7 +158,7 @@ Moralok
@@ -203,26 +203,6 @@ Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Spring Bean 加载过程
-
-
-
-
-
-
-
-
-
- Spring Bean 生命周期
-
-获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
-1
2
3
4
public Object getBean(String name) throws BeansException {
// 具体工作由 doGetBean 完成
return doGetBean(name, null, null, false);
}
-
-deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
-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
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换名称:去除 FactoryBean 的前缀 &,将别名转换为规范名称
final String beanName = transformedBeanName(name);
Object bean;
// 检查单例缓存中是否已存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
// 如果已存在,直接返回该实例或者使用该实例(FactoryBean)创建并返回对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果当前 Bean 是一个正在创建中的 prototype 类型,表明可能发生循环引用
// 注意:Spring 并未解决 prototype 类型的循环引用问题,要抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果当前 beanFactory 没有 bean 定义,去 parent beanFactory 中查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 标记为至少创建过一次
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保 bean 依赖的 bean(构造器参数) 都已实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 注意:Spring 并未解决构造器方法中的循环引用问题,要抛异常
}
// 注册依赖关系,确保先销毁被依赖的 bean
registerDependentBean(dep, beanName);
// 递归,获取依赖的 bean
getBean(dep);
}
}
}
if (mbd.isSingleton()) {
// 如果是单例类型(绝大多数都是此类型)
// 再次从缓存中获取,如果仍不存在,则使用传入的 ObjectFactory 创建
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>(
{
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);
}
else if (mbd.isPrototype()) {
// 如果是原型类型,每次都新创建一个
// ...
}
else {
// 如果是其他 scope 类型
// ...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
-
-getSingleton
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 加锁
synchronized (this.singletonObjects) {
// 再次从缓存中获取(和调用前从缓存中获取构成双重校验)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
// 如果正在销毁单例,则抛异常
// 注意:不要在销毁方法中调用获取 bean 方法
}
// 创建前,先注册到正在创建中的集合
// 在出现循环引用时,第二次进入 doGetBean,用此作为判断标志
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// ...
try {
// 使用传入的单例工厂创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 如果异常的出现是因为 bean 被创建了,就忽略异常,否则抛出异常
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
// ...
}
finally {
// ...
// 创建后,从正在创建中集合移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加单例到缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
-
-创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
-1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// ...
try {
// 给 Bean 后置处理器一个返回代理的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...
// 常规的创建 Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
-
-doCreateBean
常规的创建 Bean 的具体工作是由 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
39
40
41
42
43
44
45
46
47
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 使用相应的策略创建 bean 实例,例如通过工厂方法或者有参、无参构造器方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// ...
// 使用 ObjectFactory 封装实例并缓存,以解决循环引用问题
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
// 填充属性(包括解析依赖的 bean)
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
// ...
// 如有需要,将 bean 注册为一次性的,以供 beanFactory 在关闭时调用销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// ...
return exposedObject;
}
-
-createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
-
-- 工厂方法
-- 构造器方法
-- 有参
-- 无参
-
-
-
-populateBean
为创建出的实例填充属性,包括解析当前 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
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// ...
// 给 InstantiationAwareBeanPostProcessors 一个机会,
// 在设置 bean 属性前修改 bean 状态,可用于自定义的字段注入
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 是否继续填充属性的流程
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否存在 InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 后置处理 PropertyValues
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 将属性应用到 bean 上(常规情况下,前面的处理都用不上)
applyPropertyValues(beanName, mbd, bw, pvs);
}
-
-initializeBean
在填充完属性后,实例就可以进行初始化工作:
-
-- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息
-- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
-- invokeInitMethods,调用初始化方法
-- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
-
-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
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 处理 Aware 接口的相应方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 应用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
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()) {
// 应用 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
-
-处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
-1
2
3
4
5
6
7
8
9
10
11
12
13
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
-
-调用初始化方法
-- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法
-- 如果自定义 init 方法且满足调用条件,同样进行调用
-
-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
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 是否实现 InitializingBean 接口,是的话调用 afterPropertiesSet 方法
// 给 bean 一个感知属性已设置并做出反应的机会
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean
&& (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 如果存在自定义的 init 方法且方法名称不是 afterPropertiesSet,判断是否调用
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null
&& !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
-
-BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
-
-- 获取 Processor 列表
-- 判断 Processor 类型是否是当前需要的
-- 对 bean 进行处理
-
-1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
-
-再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
-1
2
3
4
5
6
7
8
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
-
-在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
-
-- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。
-- Bean 自身的初始化。
-
-在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -392,7 +232,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Spring Bean 加载过程
+
+
+
+
+
+
+
+
+
+ Spring Bean 生命周期
+
+获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
+1
2
3
4
public Object getBean(String name) throws BeansException {
// 具体工作由 doGetBean 完成
return doGetBean(name, null, null, false);
}
+
+deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
+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
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换名称:去除 FactoryBean 的前缀 &,将别名转换为规范名称
final String beanName = transformedBeanName(name);
Object bean;
// 检查单例缓存中是否已存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
// 如果已存在,直接返回该实例或者使用该实例(FactoryBean)创建并返回对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果当前 Bean 是一个正在创建中的 prototype 类型,表明可能发生循环引用
// 注意:Spring 并未解决 prototype 类型的循环引用问题,要抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果当前 beanFactory 没有 bean 定义,去 parent beanFactory 中查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 标记为至少创建过一次
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保 bean 依赖的 bean(构造器参数) 都已实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 注意:Spring 并未解决构造器方法中的循环引用问题,要抛异常
}
// 注册依赖关系,确保先销毁被依赖的 bean
registerDependentBean(dep, beanName);
// 递归,获取依赖的 bean
getBean(dep);
}
}
}
if (mbd.isSingleton()) {
// 如果是单例类型(绝大多数都是此类型)
// 再次从缓存中获取,如果仍不存在,则使用传入的 ObjectFactory 创建
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>(
{
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);
}
else if (mbd.isPrototype()) {
// 如果是原型类型,每次都新创建一个
// ...
}
else {
// 如果是其他 scope 类型
// ...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
+
+getSingleton
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 加锁
synchronized (this.singletonObjects) {
// 再次从缓存中获取(和调用前从缓存中获取构成双重校验)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
// 如果正在销毁单例,则抛异常
// 注意:不要在销毁方法中调用获取 bean 方法
}
// 创建前,先注册到正在创建中的集合
// 在出现循环引用时,第二次进入 doGetBean,用此作为判断标志
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// ...
try {
// 使用传入的单例工厂创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 如果异常的出现是因为 bean 被创建了,就忽略异常,否则抛出异常
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
// ...
}
finally {
// ...
// 创建后,从正在创建中集合移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加单例到缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
+
+创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// ...
try {
// 给 Bean 后置处理器一个返回代理的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...
// 常规的创建 Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
+
+doCreateBean
常规的创建 Bean 的具体工作是由 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
39
40
41
42
43
44
45
46
47
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 使用相应的策略创建 bean 实例,例如通过工厂方法或者有参、无参构造器方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// ...
// 使用 ObjectFactory 封装实例并缓存,以解决循环引用问题
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
// 填充属性(包括解析依赖的 bean)
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
// ...
// 如有需要,将 bean 注册为一次性的,以供 beanFactory 在关闭时调用销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// ...
return exposedObject;
}
+
+createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
+
+- 工厂方法
+- 构造器方法
+- 有参
+- 无参
+
+
+
+populateBean
为创建出的实例填充属性,包括解析当前 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
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// ...
// 给 InstantiationAwareBeanPostProcessors 一个机会,
// 在设置 bean 属性前修改 bean 状态,可用于自定义的字段注入
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 是否继续填充属性的流程
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否存在 InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 后置处理 PropertyValues
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 将属性应用到 bean 上(常规情况下,前面的处理都用不上)
applyPropertyValues(beanName, mbd, bw, pvs);
}
+
+initializeBean
在填充完属性后,实例就可以进行初始化工作:
+
+- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息
+- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
+- invokeInitMethods,调用初始化方法
+- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
+
+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
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 处理 Aware 接口的相应方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 应用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
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()) {
// 应用 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
+
+处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
+1
2
3
4
5
6
7
8
9
10
11
12
13
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
+
+调用初始化方法
+- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法
+- 如果自定义 init 方法且满足调用条件,同样进行调用
+
+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
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 是否实现 InitializingBean 接口,是的话调用 afterPropertiesSet 方法
// 给 bean 一个感知属性已设置并做出反应的机会
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean
&& (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 如果存在自定义的 init 方法且方法名称不是 afterPropertiesSet,判断是否调用
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null
&& !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
+
+BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
+
+- 获取 Processor 列表
+- 判断 Processor 类型是否是当前需要的
+- 对 bean 进行处理
+
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
+
+再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
+1
2
3
4
5
6
7
8
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
+
+在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
+
+- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。
+- Bean 自身的初始化。
+
+在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -1701,6 +1541,166 @@
-
+
@@ -1580,7 +1420,7 @@
-
+
@@ -1380,7 +1220,7 @@
-
+
@@ -1147,7 +987,7 @@
-
+
@@ -714,7 +554,7 @@
-
+
@@ -546,7 +386,7 @@
+
+
+
+
+
+
+
@@ -1742,7 +1742,7 @@
Moralok
-
+
diff --git a/leancloud_counter_security_urls.json b/leancloud_counter_security_urls.json
index 881386d7..3857eb32 100644
--- a/leancloud_counter_security_urls.json
+++ b/leancloud_counter_security_urls.json
@@ -1 +1 @@
-[{"title":"在 Ubuntu 上安装 Clash","url":"/2023/05/27/how-to-install-clash-on-ubuntu/"},{"title":"Docker 常用命令列表","url":"/2020/08/19/docker-frequently-used-commands/"},{"title":"在 iOS 和 macOS 上安装 OpenVPN 客户端","url":"/2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/"},{"title":"在 Windows 10 上安装 OpenVPN 服务器","url":"/2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/"},{"title":"使用 OpenVPN 访问家庭内网","url":"/2023/06/07/how-to-use-OpenVPN-to-access-home-network/"},{"title":"Ubuntu server 20.04 安装后没有分配全部磁盘空间","url":"/2023/06/24/Ubuntu-server-20-04-not-all-disk-space-was-allocated-after-installation/"},{"title":"如何使用 SSH 连接 Github 和服务器","url":"/2023/06/28/how-to-use-ssh-to-connect-github-and-server/"},{"title":"Tmux 常用命令和快捷键","url":"/2023/06/29/tmux-frequently-used-commands/"},{"title":"如何为终端、docker 和容器设置代理","url":"/2023/06/13/how-to-configure-proxy-for-terminal-docker-and-container/"},{"title":"如何在 Ubuntu 20.04 上安装 Minikube","url":"/2023/06/23/how-to-install-Minikube-on-Ubuntu-20-04/"},{"title":"JVM GC 的测试和分析","url":"/2023/11/01/testing-and-analysis-of-jvm-gc/"},{"title":"字符串常量池的测试和分析","url":"/2023/11/03/testing-and-analysis-of-StringTable/"},{"title":"Spring Bean 加载过程","url":"/2023/11/17/how-does-Spring-load-beans/"},{"title":"关于 Java 字节码指令的一些例子分析","url":"/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/"},{"title":"基于 Redis 的分布式锁的简单实现","url":"/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/"},{"title":"Java 类加载器源码分析","url":"/2023/07/13/Java-class-loader-source-code-analysis/"},{"title":"JVM 内存区域的测试和分析","url":"/2023/11/04/testing-and-analysis-of-jvm-memory-area/"},{"title":"Java 垃圾收集","url":"/2023/11/07/garbage-collection-in-Java/"}]
\ No newline at end of file
+[{"title":"在 Ubuntu 上安装 Clash","url":"/2023/05/27/how-to-install-clash-on-ubuntu/"},{"title":"在 iOS 和 macOS 上安装 OpenVPN 客户端","url":"/2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/"},{"title":"在 Windows 10 上安装 OpenVPN 服务器","url":"/2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/"},{"title":"使用 OpenVPN 访问家庭内网","url":"/2023/06/07/how-to-use-OpenVPN-to-access-home-network/"},{"title":"如何为终端、docker 和容器设置代理","url":"/2023/06/13/how-to-configure-proxy-for-terminal-docker-and-container/"},{"title":"Docker 常用命令列表","url":"/2020/08/19/docker-frequently-used-commands/"},{"title":"Ubuntu server 20.04 安装后没有分配全部磁盘空间","url":"/2023/06/24/Ubuntu-server-20-04-not-all-disk-space-was-allocated-after-installation/"},{"title":"Tmux 常用命令和快捷键","url":"/2023/06/29/tmux-frequently-used-commands/"},{"title":"如何使用 SSH 连接 Github 和服务器","url":"/2023/06/28/how-to-use-ssh-to-connect-github-and-server/"},{"title":"如何在 Ubuntu 20.04 上安装 Minikube","url":"/2023/06/23/how-to-install-Minikube-on-Ubuntu-20-04/"},{"title":"Spring Bean 加载过程","url":"/2023/08/10/how-does-Spring-load-beans/"},{"title":"JVM GC 的测试和分析","url":"/2023/11/01/testing-and-analysis-of-jvm-gc/"},{"title":"字符串常量池的测试和分析","url":"/2023/11/03/testing-and-analysis-of-StringTable/"},{"title":"Java 类加载器源码分析","url":"/2023/07/13/Java-class-loader-source-code-analysis/"},{"title":"关于 Java 字节码指令的一些例子分析","url":"/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/"},{"title":"基于 Redis 的分布式锁的简单实现","url":"/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/"},{"title":"JVM 内存区域的测试和分析","url":"/2023/11/04/testing-and-analysis-of-jvm-memory-area/"},{"title":"Java 垃圾收集","url":"/2023/11/07/garbage-collection-in-Java/"}]
\ No newline at end of file
diff --git a/page/2/index.html b/page/2/index.html
index 36d9d6ec..ab4a4a4e 100644
--- a/page/2/index.html
+++ b/page/2/index.html
@@ -158,7 +158,7 @@
-
+
@@ -2182,7 +2182,7 @@
-
+
@@ -2028,7 +2028,7 @@
@@ -232,7 +232,7 @@
proxy
+
+ 在 iOS 和 macOS 上安装 OpenVPN 客户端
+ /2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/
+ 安装 OpenVPN Connect
-
+
diff --git a/search.xml b/search.xml
index caf717a6..7947b806 100644
--- a/search.xml
+++ b/search.xml
@@ -45,6 +45,176 @@
-
+
@@ -1151,7 +1151,7 @@
-
+
@@ -1018,7 +1018,7 @@
-
+
@@ -897,7 +897,7 @@
-
+
@@ -781,7 +781,7 @@
-
+
@@ -633,7 +633,7 @@
-
+
@@ -493,7 +493,7 @@
-
+
@@ -343,7 +343,7 @@ macOS 访问官网下载。
iOS 访问 AppStore,需要登录外区 Apple ID。
+配置 OpenVPN Connect
客户端提供了两种方式导入配置文件,一是通过 URL,建议 URL 仅限在私有网络内访问,二是通过其他方式例如邮件,下载为本地文件再导入。
+配置文件的组织方式又分为两种形式,一种是将 CA 根证书 ca.crt,客户端证书 client.crt,客户端密钥 client.key 的内容复制粘贴到 client.ovpn 中,形成一个联合配置文件;另一种是使用 openssl 将 CA 根证书 ca.crt,客户端证书 client.crt,客户端密钥 client.key 转换为 PKCS#12 文件,先后导入 client.ovpn12 和 client.ovpn。
+单一 client.ovpn
从目录 C:\Program Files\OpenVPN\sample-config
复制客户端配置文件模板 client.ovpn,修改以下配置:
+remote your-server 1194
;ca ca.crt
;cert client.crt
;key client.key
;tls-auth ta.key 1
<ca>
-----BEGIN CERTIFICATE-----
paste contents of ca.crt
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
paste contents of client.crt
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
paste contents of client.key
-----END PRIVATE KEY-----
</key>
+将 remote your-server 1194
中的地址和端口替换成你的 OpenVPN server 的地址和端口。将 ca ca.crt
, cert client.crt
, key client.key
, tls-auth ta.key 1
注释掉,将各自文件中的内容以上述类 XML 的形式粘贴到 client.ovpn 中。
+将修改好的客户端配置文件导入到客户端中即可。
+client.ovpn + client.opvn12
使用 openssl 命令将客户端的证书和私钥文件转换为 PKCS#12 形式的文件。该命令会提示 Enter Export Password
,可以为空,但为了安全建议设置密码。
+openssl pkcs12 -export -in cert -inkey key -certfile ca -name MyClient -out client.ovpn12
+由于在 iOS 中导入 PKCS#12 文件到 Keychain 中时只导入了客户端证书和密钥,CA 根证书并没有导入,client.ovpn 文件中必须要保留 CA 根证书的配置。
既可以用传统的引用文件的方式:
+ca ca.crt
+也可以用类 XML 的形式粘贴 ca.crt 内容到 client.ovpn 中:
+<ca>
paste contents of ca.crt here
</ca>
+先导入 client.ovpn12(需要输入转换时的密码),再导入 client.ovpn。
+
+但是我失败了……导入 client.ovpn12 时密码一直错误,搜索到类似的案例,但是没有找到解决方案。不确定是不是 openssl 版本引起的。
+
+路由器 NAT
在路由器管理后台的 NAT 设置功能里,配置好对外端口号和 Windows 10 主机上 OpenVPN 端口号的映射关系。
+参考链接
iOS 使用 OpenVPN 的 FAQ
如何通过 iOS Keychain 使用客户端证书和密钥
如何配置 iOS OpenVPN 客户端的证书认证
+]]>
+
+ openvpn
+
+
+
+ 在 Windows 10 上安装 OpenVPN 服务器
+ /2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/
+ 安装 OpenVPN server
@@ -191,166 +191,6 @@
@@ -203,26 +203,6 @@
@@ -203,26 +203,6 @@
-
+
@@ -359,9 +359,6 @@ 从 OpenVPN 社区 下载 Windows 64-bit MSI installer。本次安装的版本为 OpenVPN 2.6.4。
+
+注意事项:在选择安装类型时选择 Customize 而不要选择 Install Now。额外勾选 OpenVPN -> OpenVPN Service -> Entire feature will be installed on local hard drive 和 OpenSSL Utilities -> EasyRSA 3 Certificate Management Scripts -> Entire feature will be installed on local hard drive。
+
+安装完毕后,会弹出一条消息提示未找到可读的连接配置文件,暂时忽略。
此时在 控制面板\网络和 Internet\网络连接 中可以看到创建了两个新的网络适配器 OpenVPN TAP-Windows6 和 OpenVPN Wintun。
+配置 OpenVPN server
打开 Windows 10 终端程序。
进入 OpenVPN 默认安装目录中的 easy-rsa 目录。
+cd 'C:\Program Files\OpenVPN\easy-rsa'
+执行命令进入 Easy-RSA 3 Shell
+.\EasyRSA-Start.bat
+初始化公钥基础设施目录 pki
+./easyrsa init-pki
+构建证书颁发机构(CA)密钥,CA 根证书文件将在后续用于对其他证书和密钥进行签名。该命令要求输入 Common Name,输入主机名即可。创建的 ca.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki
中,ca.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
+./easyrsa build-ca nopass
+构建服务器证书和密钥。创建的 server.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\issued
中,server.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
+./easyrsa build-server-full server nopass
+构建客户端证书和密钥。创建的 client.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\issued
中,client.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
+./easyrsa build-client-full client nopass
+生成 Diffie-Hellman 参数
+./easyrsa gen-dh
+从目录 C:\Program Files\OpenVPN\sample-config
复制服务端配置文件模板 server.ovpn 到目录 C:\Program Files\OpenVPN\config
中,修改以下配置:
+port 1194
dh dh.pem
duplicate-cn
;tls-auth ta.key 0
+端口号按需修改,默认为1194,需要保证 OpenVPN 的网络流量可以通过防火墙,设置 Windows 10 Defender 允许 OpenVPN 通过即可。dh2048.pem 修改为生成的文件名 dh.pem。取消注释 duplicate-cn,让多个客户端使用同一个客户端证书。注释掉 tls-auth ta.key 0。复制 ca.crt,dh.pem,server.crt 和 server.key 到目录 C:\Program Files\OpenVPN\config 中。
+启动与连接
启动 OpenVPN,点击连接,系统提示分配 IP 10.8.0.1。按配置,每次 OpenVPN server 都将为自己分配 10.8.0.1。
+参考链接
openvpn安装配置说明(windows系统)
如何在Windows 10上安装和配置OpenVPN
+]]>
+
+ openvpn
+
+
+
+ 使用 OpenVPN 访问家庭内网
+ /2023/06/07/how-to-use-OpenVPN-to-access-home-network/
+ 网络概况
diff --git a/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html b/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html
index 9bff8d7e..f765d3b9 100644
--- a/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html
+++ b/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html
@@ -33,7 +33,7 @@
-
+
@@ -170,7 +170,7 @@
@@ -245,7 +245,7 @@
-
+
@@ -355,7 +355,7 @@ 宽带是电信宽带,分配了动态的公网 IP。
光猫使用桥接模式,通过路由器拨号上网(PPPoE),路由器局域网为 192.168.3.0/24。
一台 Windows 10 主机,在路由器局域网上的 IP 192.168.3.120。。
Windows 10 主机上运行 Vmware 虚拟机,网络采用 NAT 模式。子网为 192.168.46.0/24。运行了 Linux 主机,IP 192.168.46.128。Windows 10 主机在子网中的 IP 为 192.168.3.1。
+
diff --git a/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/index.html b/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/index.html
index 66a39560..04068448 100644
--- a/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/index.html
+++ b/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/index.html
@@ -28,9 +28,9 @@
-
+
-
+
@@ -165,7 +165,7 @@
@@ -240,7 +240,7 @@
-
+
@@ -626,7 +626,7 @@
diff --git a/2023/11/07/garbage-collection-in-Java/index.html b/2023/11/07/garbage-collection-in-Java/index.html
index 48c53b1f..1d18ff48 100644
--- a/2023/11/07/garbage-collection-in-Java/index.html
+++ b/2023/11/07/garbage-collection-in-Java/index.html
@@ -34,9 +34,9 @@
-
+
-
+
@@ -171,7 +171,7 @@
@@ -246,7 +246,7 @@
-
+
@@ -424,7 +424,7 @@
-
- Spring Bean 加载过程
-
diff --git a/archives/2020/08/index.html b/archives/2020/08/index.html
index 5cb2fa4a..9a8aec9a 100644
--- a/archives/2020/08/index.html
+++ b/archives/2020/08/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2020/index.html b/archives/2020/index.html
index 4c74ba98..18e0f275 100644
--- a/archives/2020/index.html
+++ b/archives/2020/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/05/index.html b/archives/2023/05/index.html
index 539bcf0e..183b92da 100644
--- a/archives/2023/05/index.html
+++ b/archives/2023/05/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/06/index.html b/archives/2023/06/index.html
index be634e2c..5272063f 100644
--- a/archives/2023/06/index.html
+++ b/archives/2023/06/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/07/index.html b/archives/2023/07/index.html
index 7f1c535f..1cb43f2f 100644
--- a/archives/2023/07/index.html
+++ b/archives/2023/07/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/tags/Java/index.html b/archives/2023/08/index.html
similarity index 70%
rename from tags/Java/index.html
rename to archives/2023/08/index.html
index 94638b7d..4aa36998 100644
--- a/tags/Java/index.html
+++ b/archives/2023/08/index.html
@@ -22,7 +22,7 @@
-
+
@@ -30,14 +30,14 @@
-
+
-
+
-标签: Java | Moralok
+归档 | Moralok
@@ -68,7 +68,7 @@
- Moralok
+ Moralok
@@ -158,7 +158,7 @@
@@ -186,7 +186,7 @@
-
+
@@ -195,9 +195,7 @@
- Java
- 标签
-
+ 嗯..! 目前共计 18 篇日志。 继续努力。
@@ -209,15 +207,15 @@ Java
@@ -225,105 +223,6 @@ Java
-
-
-
-
- Java 垃圾收集
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 字符串常量池的测试和分析
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/archives/2023/11/index.html b/archives/2023/11/index.html
index 38cea205..ece70fec 100644
--- a/archives/2023/11/index.html
+++ b/archives/2023/11/index.html
@@ -158,7 +158,7 @@ Moralok
@@ -203,26 +203,6 @@ Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Spring Bean 加载过程
-
-
-
-
-
-
-
-
-
- Spring Bean 生命周期
-
-获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
-1
2
3
4
public Object getBean(String name) throws BeansException {
// 具体工作由 doGetBean 完成
return doGetBean(name, null, null, false);
}
-
-deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
-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
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换名称:去除 FactoryBean 的前缀 &,将别名转换为规范名称
final String beanName = transformedBeanName(name);
Object bean;
// 检查单例缓存中是否已存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
// 如果已存在,直接返回该实例或者使用该实例(FactoryBean)创建并返回对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果当前 Bean 是一个正在创建中的 prototype 类型,表明可能发生循环引用
// 注意:Spring 并未解决 prototype 类型的循环引用问题,要抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果当前 beanFactory 没有 bean 定义,去 parent beanFactory 中查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 标记为至少创建过一次
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保 bean 依赖的 bean(构造器参数) 都已实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 注意:Spring 并未解决构造器方法中的循环引用问题,要抛异常
}
// 注册依赖关系,确保先销毁被依赖的 bean
registerDependentBean(dep, beanName);
// 递归,获取依赖的 bean
getBean(dep);
}
}
}
if (mbd.isSingleton()) {
// 如果是单例类型(绝大多数都是此类型)
// 再次从缓存中获取,如果仍不存在,则使用传入的 ObjectFactory 创建
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>(
{
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);
}
else if (mbd.isPrototype()) {
// 如果是原型类型,每次都新创建一个
// ...
}
else {
// 如果是其他 scope 类型
// ...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
-
-getSingleton
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 加锁
synchronized (this.singletonObjects) {
// 再次从缓存中获取(和调用前从缓存中获取构成双重校验)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
// 如果正在销毁单例,则抛异常
// 注意:不要在销毁方法中调用获取 bean 方法
}
// 创建前,先注册到正在创建中的集合
// 在出现循环引用时,第二次进入 doGetBean,用此作为判断标志
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// ...
try {
// 使用传入的单例工厂创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 如果异常的出现是因为 bean 被创建了,就忽略异常,否则抛出异常
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
// ...
}
finally {
// ...
// 创建后,从正在创建中集合移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加单例到缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
-
-创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
-1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// ...
try {
// 给 Bean 后置处理器一个返回代理的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...
// 常规的创建 Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
-
-doCreateBean
常规的创建 Bean 的具体工作是由 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
39
40
41
42
43
44
45
46
47
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 使用相应的策略创建 bean 实例,例如通过工厂方法或者有参、无参构造器方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// ...
// 使用 ObjectFactory 封装实例并缓存,以解决循环引用问题
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
// 填充属性(包括解析依赖的 bean)
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
// ...
// 如有需要,将 bean 注册为一次性的,以供 beanFactory 在关闭时调用销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// ...
return exposedObject;
}
-
-createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
-
-- 工厂方法
-- 构造器方法
-- 有参
-- 无参
-
-
-
-populateBean
为创建出的实例填充属性,包括解析当前 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
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// ...
// 给 InstantiationAwareBeanPostProcessors 一个机会,
// 在设置 bean 属性前修改 bean 状态,可用于自定义的字段注入
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 是否继续填充属性的流程
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否存在 InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 后置处理 PropertyValues
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 将属性应用到 bean 上(常规情况下,前面的处理都用不上)
applyPropertyValues(beanName, mbd, bw, pvs);
}
-
-initializeBean
在填充完属性后,实例就可以进行初始化工作:
-
-- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息
-- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
-- invokeInitMethods,调用初始化方法
-- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
-
-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
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 处理 Aware 接口的相应方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 应用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
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()) {
// 应用 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
-
-处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
-1
2
3
4
5
6
7
8
9
10
11
12
13
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
-
-调用初始化方法
-- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法
-- 如果自定义 init 方法且满足调用条件,同样进行调用
-
-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
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 是否实现 InitializingBean 接口,是的话调用 afterPropertiesSet 方法
// 给 bean 一个感知属性已设置并做出反应的机会
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean
&& (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 如果存在自定义的 init 方法且方法名称不是 afterPropertiesSet,判断是否调用
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null
&& !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
-
-BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
-
-- 获取 Processor 列表
-- 判断 Processor 类型是否是当前需要的
-- 对 bean 进行处理
-
-1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
-
-再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
-1
2
3
4
5
6
7
8
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
-
-在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
-
-- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。
-- Bean 自身的初始化。
-
-在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -392,7 +232,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Spring Bean 加载过程
+
+
+
+
+
+
+
+
+
+ Spring Bean 生命周期
+
+获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
+1
2
3
4
public Object getBean(String name) throws BeansException {
// 具体工作由 doGetBean 完成
return doGetBean(name, null, null, false);
}
+
+deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
+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
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换名称:去除 FactoryBean 的前缀 &,将别名转换为规范名称
final String beanName = transformedBeanName(name);
Object bean;
// 检查单例缓存中是否已存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
// 如果已存在,直接返回该实例或者使用该实例(FactoryBean)创建并返回对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果当前 Bean 是一个正在创建中的 prototype 类型,表明可能发生循环引用
// 注意:Spring 并未解决 prototype 类型的循环引用问题,要抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果当前 beanFactory 没有 bean 定义,去 parent beanFactory 中查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 标记为至少创建过一次
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保 bean 依赖的 bean(构造器参数) 都已实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 注意:Spring 并未解决构造器方法中的循环引用问题,要抛异常
}
// 注册依赖关系,确保先销毁被依赖的 bean
registerDependentBean(dep, beanName);
// 递归,获取依赖的 bean
getBean(dep);
}
}
}
if (mbd.isSingleton()) {
// 如果是单例类型(绝大多数都是此类型)
// 再次从缓存中获取,如果仍不存在,则使用传入的 ObjectFactory 创建
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>(
{
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);
}
else if (mbd.isPrototype()) {
// 如果是原型类型,每次都新创建一个
// ...
}
else {
// 如果是其他 scope 类型
// ...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
+
+getSingleton
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 加锁
synchronized (this.singletonObjects) {
// 再次从缓存中获取(和调用前从缓存中获取构成双重校验)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
// 如果正在销毁单例,则抛异常
// 注意:不要在销毁方法中调用获取 bean 方法
}
// 创建前,先注册到正在创建中的集合
// 在出现循环引用时,第二次进入 doGetBean,用此作为判断标志
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// ...
try {
// 使用传入的单例工厂创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 如果异常的出现是因为 bean 被创建了,就忽略异常,否则抛出异常
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
// ...
}
finally {
// ...
// 创建后,从正在创建中集合移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加单例到缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
+
+创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// ...
try {
// 给 Bean 后置处理器一个返回代理的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...
// 常规的创建 Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
+
+doCreateBean
常规的创建 Bean 的具体工作是由 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
39
40
41
42
43
44
45
46
47
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 使用相应的策略创建 bean 实例,例如通过工厂方法或者有参、无参构造器方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// ...
// 使用 ObjectFactory 封装实例并缓存,以解决循环引用问题
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
// 填充属性(包括解析依赖的 bean)
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
// ...
// 如有需要,将 bean 注册为一次性的,以供 beanFactory 在关闭时调用销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// ...
return exposedObject;
}
+
+createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
+
+- 工厂方法
+- 构造器方法
+- 有参
+- 无参
+
+
+
+populateBean
为创建出的实例填充属性,包括解析当前 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
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// ...
// 给 InstantiationAwareBeanPostProcessors 一个机会,
// 在设置 bean 属性前修改 bean 状态,可用于自定义的字段注入
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 是否继续填充属性的流程
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否存在 InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 后置处理 PropertyValues
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 将属性应用到 bean 上(常规情况下,前面的处理都用不上)
applyPropertyValues(beanName, mbd, bw, pvs);
}
+
+initializeBean
在填充完属性后,实例就可以进行初始化工作:
+
+- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息
+- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
+- invokeInitMethods,调用初始化方法
+- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
+
+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
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 处理 Aware 接口的相应方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 应用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
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()) {
// 应用 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
+
+处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
+1
2
3
4
5
6
7
8
9
10
11
12
13
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
+
+调用初始化方法
+- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法
+- 如果自定义 init 方法且满足调用条件,同样进行调用
+
+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
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 是否实现 InitializingBean 接口,是的话调用 afterPropertiesSet 方法
// 给 bean 一个感知属性已设置并做出反应的机会
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean
&& (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 如果存在自定义的 init 方法且方法名称不是 afterPropertiesSet,判断是否调用
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null
&& !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
+
+BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
+
+- 获取 Processor 列表
+- 判断 Processor 类型是否是当前需要的
+- 对 bean 进行处理
+
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
+
+再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
+1
2
3
4
5
6
7
8
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
+
+在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
+
+- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。
+- Bean 自身的初始化。
+
+在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -1701,6 +1541,166 @@
-
+
@@ -1580,7 +1420,7 @@
-
+
@@ -1380,7 +1220,7 @@
-
+
@@ -1147,7 +987,7 @@
-
+
@@ -714,7 +554,7 @@
-
+
@@ -546,7 +386,7 @@
+
+
+
+
+
+
+
@@ -1742,7 +1742,7 @@
Moralok
-
+
diff --git a/leancloud_counter_security_urls.json b/leancloud_counter_security_urls.json
index 881386d7..3857eb32 100644
--- a/leancloud_counter_security_urls.json
+++ b/leancloud_counter_security_urls.json
@@ -1 +1 @@
-[{"title":"在 Ubuntu 上安装 Clash","url":"/2023/05/27/how-to-install-clash-on-ubuntu/"},{"title":"Docker 常用命令列表","url":"/2020/08/19/docker-frequently-used-commands/"},{"title":"在 iOS 和 macOS 上安装 OpenVPN 客户端","url":"/2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/"},{"title":"在 Windows 10 上安装 OpenVPN 服务器","url":"/2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/"},{"title":"使用 OpenVPN 访问家庭内网","url":"/2023/06/07/how-to-use-OpenVPN-to-access-home-network/"},{"title":"Ubuntu server 20.04 安装后没有分配全部磁盘空间","url":"/2023/06/24/Ubuntu-server-20-04-not-all-disk-space-was-allocated-after-installation/"},{"title":"如何使用 SSH 连接 Github 和服务器","url":"/2023/06/28/how-to-use-ssh-to-connect-github-and-server/"},{"title":"Tmux 常用命令和快捷键","url":"/2023/06/29/tmux-frequently-used-commands/"},{"title":"如何为终端、docker 和容器设置代理","url":"/2023/06/13/how-to-configure-proxy-for-terminal-docker-and-container/"},{"title":"如何在 Ubuntu 20.04 上安装 Minikube","url":"/2023/06/23/how-to-install-Minikube-on-Ubuntu-20-04/"},{"title":"JVM GC 的测试和分析","url":"/2023/11/01/testing-and-analysis-of-jvm-gc/"},{"title":"字符串常量池的测试和分析","url":"/2023/11/03/testing-and-analysis-of-StringTable/"},{"title":"Spring Bean 加载过程","url":"/2023/11/17/how-does-Spring-load-beans/"},{"title":"关于 Java 字节码指令的一些例子分析","url":"/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/"},{"title":"基于 Redis 的分布式锁的简单实现","url":"/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/"},{"title":"Java 类加载器源码分析","url":"/2023/07/13/Java-class-loader-source-code-analysis/"},{"title":"JVM 内存区域的测试和分析","url":"/2023/11/04/testing-and-analysis-of-jvm-memory-area/"},{"title":"Java 垃圾收集","url":"/2023/11/07/garbage-collection-in-Java/"}]
\ No newline at end of file
+[{"title":"在 Ubuntu 上安装 Clash","url":"/2023/05/27/how-to-install-clash-on-ubuntu/"},{"title":"在 iOS 和 macOS 上安装 OpenVPN 客户端","url":"/2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/"},{"title":"在 Windows 10 上安装 OpenVPN 服务器","url":"/2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/"},{"title":"使用 OpenVPN 访问家庭内网","url":"/2023/06/07/how-to-use-OpenVPN-to-access-home-network/"},{"title":"如何为终端、docker 和容器设置代理","url":"/2023/06/13/how-to-configure-proxy-for-terminal-docker-and-container/"},{"title":"Docker 常用命令列表","url":"/2020/08/19/docker-frequently-used-commands/"},{"title":"Ubuntu server 20.04 安装后没有分配全部磁盘空间","url":"/2023/06/24/Ubuntu-server-20-04-not-all-disk-space-was-allocated-after-installation/"},{"title":"Tmux 常用命令和快捷键","url":"/2023/06/29/tmux-frequently-used-commands/"},{"title":"如何使用 SSH 连接 Github 和服务器","url":"/2023/06/28/how-to-use-ssh-to-connect-github-and-server/"},{"title":"如何在 Ubuntu 20.04 上安装 Minikube","url":"/2023/06/23/how-to-install-Minikube-on-Ubuntu-20-04/"},{"title":"Spring Bean 加载过程","url":"/2023/08/10/how-does-Spring-load-beans/"},{"title":"JVM GC 的测试和分析","url":"/2023/11/01/testing-and-analysis-of-jvm-gc/"},{"title":"字符串常量池的测试和分析","url":"/2023/11/03/testing-and-analysis-of-StringTable/"},{"title":"Java 类加载器源码分析","url":"/2023/07/13/Java-class-loader-source-code-analysis/"},{"title":"关于 Java 字节码指令的一些例子分析","url":"/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/"},{"title":"基于 Redis 的分布式锁的简单实现","url":"/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/"},{"title":"JVM 内存区域的测试和分析","url":"/2023/11/04/testing-and-analysis-of-jvm-memory-area/"},{"title":"Java 垃圾收集","url":"/2023/11/07/garbage-collection-in-Java/"}]
\ No newline at end of file
diff --git a/page/2/index.html b/page/2/index.html
index 36d9d6ec..ab4a4a4e 100644
--- a/page/2/index.html
+++ b/page/2/index.html
@@ -158,7 +158,7 @@
-
+
@@ -2182,7 +2182,7 @@
-
+
@@ -2028,7 +2028,7 @@
@@ -232,7 +232,7 @@
proxy
+
+ 在 iOS 和 macOS 上安装 OpenVPN 客户端
+ /2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/
+ 安装 OpenVPN Connect
-
+
diff --git a/search.xml b/search.xml
index caf717a6..7947b806 100644
--- a/search.xml
+++ b/search.xml
@@ -45,6 +45,176 @@
-
+
@@ -1151,7 +1151,7 @@
-
+
@@ -1018,7 +1018,7 @@
-
+
@@ -897,7 +897,7 @@
-
+
@@ -781,7 +781,7 @@
-
+
@@ -633,7 +633,7 @@
-
+
@@ -493,7 +493,7 @@
-
+
@@ -343,7 +343,7 @@ macOS 访问官网下载。
iOS 访问 AppStore,需要登录外区 Apple ID。
+配置 OpenVPN Connect
客户端提供了两种方式导入配置文件,一是通过 URL,建议 URL 仅限在私有网络内访问,二是通过其他方式例如邮件,下载为本地文件再导入。
+配置文件的组织方式又分为两种形式,一种是将 CA 根证书 ca.crt,客户端证书 client.crt,客户端密钥 client.key 的内容复制粘贴到 client.ovpn 中,形成一个联合配置文件;另一种是使用 openssl 将 CA 根证书 ca.crt,客户端证书 client.crt,客户端密钥 client.key 转换为 PKCS#12 文件,先后导入 client.ovpn12 和 client.ovpn。
+单一 client.ovpn
从目录 C:\Program Files\OpenVPN\sample-config
复制客户端配置文件模板 client.ovpn,修改以下配置:
+remote your-server 1194
;ca ca.crt
;cert client.crt
;key client.key
;tls-auth ta.key 1
<ca>
-----BEGIN CERTIFICATE-----
paste contents of ca.crt
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
paste contents of client.crt
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
paste contents of client.key
-----END PRIVATE KEY-----
</key>
+将 remote your-server 1194
中的地址和端口替换成你的 OpenVPN server 的地址和端口。将 ca ca.crt
, cert client.crt
, key client.key
, tls-auth ta.key 1
注释掉,将各自文件中的内容以上述类 XML 的形式粘贴到 client.ovpn 中。
+将修改好的客户端配置文件导入到客户端中即可。
+client.ovpn + client.opvn12
使用 openssl 命令将客户端的证书和私钥文件转换为 PKCS#12 形式的文件。该命令会提示 Enter Export Password
,可以为空,但为了安全建议设置密码。
+openssl pkcs12 -export -in cert -inkey key -certfile ca -name MyClient -out client.ovpn12
+由于在 iOS 中导入 PKCS#12 文件到 Keychain 中时只导入了客户端证书和密钥,CA 根证书并没有导入,client.ovpn 文件中必须要保留 CA 根证书的配置。
既可以用传统的引用文件的方式:
+ca ca.crt
+也可以用类 XML 的形式粘贴 ca.crt 内容到 client.ovpn 中:
+<ca>
paste contents of ca.crt here
</ca>
+先导入 client.ovpn12(需要输入转换时的密码),再导入 client.ovpn。
+
+但是我失败了……导入 client.ovpn12 时密码一直错误,搜索到类似的案例,但是没有找到解决方案。不确定是不是 openssl 版本引起的。
+
+路由器 NAT
在路由器管理后台的 NAT 设置功能里,配置好对外端口号和 Windows 10 主机上 OpenVPN 端口号的映射关系。
+参考链接
iOS 使用 OpenVPN 的 FAQ
如何通过 iOS Keychain 使用客户端证书和密钥
如何配置 iOS OpenVPN 客户端的证书认证
+]]>
+
+ openvpn
+
+
+
+ 在 Windows 10 上安装 OpenVPN 服务器
+ /2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/
+ 安装 OpenVPN server
@@ -191,166 +191,6 @@
@@ -203,26 +203,6 @@
@@ -203,26 +203,6 @@
-
+
@@ -359,9 +359,6 @@ 从 OpenVPN 社区 下载 Windows 64-bit MSI installer。本次安装的版本为 OpenVPN 2.6.4。
+
+注意事项:在选择安装类型时选择 Customize 而不要选择 Install Now。额外勾选 OpenVPN -> OpenVPN Service -> Entire feature will be installed on local hard drive 和 OpenSSL Utilities -> EasyRSA 3 Certificate Management Scripts -> Entire feature will be installed on local hard drive。
+
+安装完毕后,会弹出一条消息提示未找到可读的连接配置文件,暂时忽略。
此时在 控制面板\网络和 Internet\网络连接 中可以看到创建了两个新的网络适配器 OpenVPN TAP-Windows6 和 OpenVPN Wintun。
+配置 OpenVPN server
打开 Windows 10 终端程序。
进入 OpenVPN 默认安装目录中的 easy-rsa 目录。
+cd 'C:\Program Files\OpenVPN\easy-rsa'
+执行命令进入 Easy-RSA 3 Shell
+.\EasyRSA-Start.bat
+初始化公钥基础设施目录 pki
+./easyrsa init-pki
+构建证书颁发机构(CA)密钥,CA 根证书文件将在后续用于对其他证书和密钥进行签名。该命令要求输入 Common Name,输入主机名即可。创建的 ca.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki
中,ca.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
+./easyrsa build-ca nopass
+构建服务器证书和密钥。创建的 server.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\issued
中,server.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
+./easyrsa build-server-full server nopass
+构建客户端证书和密钥。创建的 client.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\issued
中,client.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
+./easyrsa build-client-full client nopass
+生成 Diffie-Hellman 参数
+./easyrsa gen-dh
+从目录 C:\Program Files\OpenVPN\sample-config
复制服务端配置文件模板 server.ovpn 到目录 C:\Program Files\OpenVPN\config
中,修改以下配置:
+port 1194
dh dh.pem
duplicate-cn
;tls-auth ta.key 0
+端口号按需修改,默认为1194,需要保证 OpenVPN 的网络流量可以通过防火墙,设置 Windows 10 Defender 允许 OpenVPN 通过即可。dh2048.pem 修改为生成的文件名 dh.pem。取消注释 duplicate-cn,让多个客户端使用同一个客户端证书。注释掉 tls-auth ta.key 0。复制 ca.crt,dh.pem,server.crt 和 server.key 到目录 C:\Program Files\OpenVPN\config 中。
+启动与连接
启动 OpenVPN,点击连接,系统提示分配 IP 10.8.0.1。按配置,每次 OpenVPN server 都将为自己分配 10.8.0.1。
+参考链接
openvpn安装配置说明(windows系统)
如何在Windows 10上安装和配置OpenVPN
+]]>
+
+ openvpn
+
+
+
+ 使用 OpenVPN 访问家庭内网
+ /2023/06/07/how-to-use-OpenVPN-to-access-home-network/
+ 网络概况
diff --git a/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html b/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html
index 9bff8d7e..f765d3b9 100644
--- a/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html
+++ b/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html
@@ -33,7 +33,7 @@
-
+
@@ -170,7 +170,7 @@
@@ -245,7 +245,7 @@
-
+
@@ -355,7 +355,7 @@ 宽带是电信宽带,分配了动态的公网 IP。
光猫使用桥接模式,通过路由器拨号上网(PPPoE),路由器局域网为 192.168.3.0/24。
一台 Windows 10 主机,在路由器局域网上的 IP 192.168.3.120。。
Windows 10 主机上运行 Vmware 虚拟机,网络采用 NAT 模式。子网为 192.168.46.0/24。运行了 Linux 主机,IP 192.168.46.128。Windows 10 主机在子网中的 IP 为 192.168.3.1。
+
diff --git a/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/index.html b/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/index.html
index 66a39560..04068448 100644
--- a/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/index.html
+++ b/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/index.html
@@ -28,9 +28,9 @@
-
+
-
+
@@ -165,7 +165,7 @@
@@ -240,7 +240,7 @@
-
+
@@ -626,7 +626,7 @@
-
- Spring Bean 加载过程
-
diff --git a/archives/2020/08/index.html b/archives/2020/08/index.html
index 5cb2fa4a..9a8aec9a 100644
--- a/archives/2020/08/index.html
+++ b/archives/2020/08/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2020/index.html b/archives/2020/index.html
index 4c74ba98..18e0f275 100644
--- a/archives/2020/index.html
+++ b/archives/2020/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/05/index.html b/archives/2023/05/index.html
index 539bcf0e..183b92da 100644
--- a/archives/2023/05/index.html
+++ b/archives/2023/05/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/06/index.html b/archives/2023/06/index.html
index be634e2c..5272063f 100644
--- a/archives/2023/06/index.html
+++ b/archives/2023/06/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/07/index.html b/archives/2023/07/index.html
index 7f1c535f..1cb43f2f 100644
--- a/archives/2023/07/index.html
+++ b/archives/2023/07/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/tags/Java/index.html b/archives/2023/08/index.html
similarity index 70%
rename from tags/Java/index.html
rename to archives/2023/08/index.html
index 94638b7d..4aa36998 100644
--- a/tags/Java/index.html
+++ b/archives/2023/08/index.html
@@ -22,7 +22,7 @@
-
+
@@ -30,14 +30,14 @@
-
+
-
+
-标签: Java | Moralok
+归档 | Moralok
@@ -68,7 +68,7 @@
- Moralok
+ Moralok
@@ -158,7 +158,7 @@
@@ -186,7 +186,7 @@
-
+
@@ -195,9 +195,7 @@
- Java
- 标签
-
+ 嗯..! 目前共计 18 篇日志。 继续努力。
@@ -209,15 +207,15 @@ Java
@@ -225,105 +223,6 @@ Java
-
-
-
-
- Java 垃圾收集
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 字符串常量池的测试和分析
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/archives/2023/11/index.html b/archives/2023/11/index.html
index 38cea205..ece70fec 100644
--- a/archives/2023/11/index.html
+++ b/archives/2023/11/index.html
@@ -158,7 +158,7 @@ Moralok
@@ -203,26 +203,6 @@ Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Spring Bean 加载过程
-
-
-
-
-
-
-
-
-
- Spring Bean 生命周期
-
-获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
-1
2
3
4
public Object getBean(String name) throws BeansException {
// 具体工作由 doGetBean 完成
return doGetBean(name, null, null, false);
}
-
-deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
-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
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换名称:去除 FactoryBean 的前缀 &,将别名转换为规范名称
final String beanName = transformedBeanName(name);
Object bean;
// 检查单例缓存中是否已存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
// 如果已存在,直接返回该实例或者使用该实例(FactoryBean)创建并返回对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果当前 Bean 是一个正在创建中的 prototype 类型,表明可能发生循环引用
// 注意:Spring 并未解决 prototype 类型的循环引用问题,要抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果当前 beanFactory 没有 bean 定义,去 parent beanFactory 中查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 标记为至少创建过一次
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保 bean 依赖的 bean(构造器参数) 都已实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 注意:Spring 并未解决构造器方法中的循环引用问题,要抛异常
}
// 注册依赖关系,确保先销毁被依赖的 bean
registerDependentBean(dep, beanName);
// 递归,获取依赖的 bean
getBean(dep);
}
}
}
if (mbd.isSingleton()) {
// 如果是单例类型(绝大多数都是此类型)
// 再次从缓存中获取,如果仍不存在,则使用传入的 ObjectFactory 创建
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>(
{
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);
}
else if (mbd.isPrototype()) {
// 如果是原型类型,每次都新创建一个
// ...
}
else {
// 如果是其他 scope 类型
// ...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
-
-getSingleton
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 加锁
synchronized (this.singletonObjects) {
// 再次从缓存中获取(和调用前从缓存中获取构成双重校验)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
// 如果正在销毁单例,则抛异常
// 注意:不要在销毁方法中调用获取 bean 方法
}
// 创建前,先注册到正在创建中的集合
// 在出现循环引用时,第二次进入 doGetBean,用此作为判断标志
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// ...
try {
// 使用传入的单例工厂创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 如果异常的出现是因为 bean 被创建了,就忽略异常,否则抛出异常
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
// ...
}
finally {
// ...
// 创建后,从正在创建中集合移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加单例到缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
-
-创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
-1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// ...
try {
// 给 Bean 后置处理器一个返回代理的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...
// 常规的创建 Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
-
-doCreateBean
常规的创建 Bean 的具体工作是由 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
39
40
41
42
43
44
45
46
47
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 使用相应的策略创建 bean 实例,例如通过工厂方法或者有参、无参构造器方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// ...
// 使用 ObjectFactory 封装实例并缓存,以解决循环引用问题
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
// 填充属性(包括解析依赖的 bean)
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
// ...
// 如有需要,将 bean 注册为一次性的,以供 beanFactory 在关闭时调用销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// ...
return exposedObject;
}
-
-createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
-
-- 工厂方法
-- 构造器方法
-- 有参
-- 无参
-
-
-
-populateBean
为创建出的实例填充属性,包括解析当前 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
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// ...
// 给 InstantiationAwareBeanPostProcessors 一个机会,
// 在设置 bean 属性前修改 bean 状态,可用于自定义的字段注入
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 是否继续填充属性的流程
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否存在 InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 后置处理 PropertyValues
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 将属性应用到 bean 上(常规情况下,前面的处理都用不上)
applyPropertyValues(beanName, mbd, bw, pvs);
}
-
-initializeBean
在填充完属性后,实例就可以进行初始化工作:
-
-- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息
-- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
-- invokeInitMethods,调用初始化方法
-- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
-
-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
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 处理 Aware 接口的相应方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 应用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
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()) {
// 应用 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
-
-处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
-1
2
3
4
5
6
7
8
9
10
11
12
13
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
-
-调用初始化方法
-- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法
-- 如果自定义 init 方法且满足调用条件,同样进行调用
-
-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
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 是否实现 InitializingBean 接口,是的话调用 afterPropertiesSet 方法
// 给 bean 一个感知属性已设置并做出反应的机会
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean
&& (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 如果存在自定义的 init 方法且方法名称不是 afterPropertiesSet,判断是否调用
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null
&& !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
-
-BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
-
-- 获取 Processor 列表
-- 判断 Processor 类型是否是当前需要的
-- 对 bean 进行处理
-
-1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
-
-再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
-1
2
3
4
5
6
7
8
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
-
-在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
-
-- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。
-- Bean 自身的初始化。
-
-在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -392,7 +232,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Spring Bean 加载过程
+
+
+
+
+
+
+
+
+
+ Spring Bean 生命周期
+
+获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
+1
2
3
4
public Object getBean(String name) throws BeansException {
// 具体工作由 doGetBean 完成
return doGetBean(name, null, null, false);
}
+
+deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
+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
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换名称:去除 FactoryBean 的前缀 &,将别名转换为规范名称
final String beanName = transformedBeanName(name);
Object bean;
// 检查单例缓存中是否已存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
// 如果已存在,直接返回该实例或者使用该实例(FactoryBean)创建并返回对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果当前 Bean 是一个正在创建中的 prototype 类型,表明可能发生循环引用
// 注意:Spring 并未解决 prototype 类型的循环引用问题,要抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果当前 beanFactory 没有 bean 定义,去 parent beanFactory 中查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 标记为至少创建过一次
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保 bean 依赖的 bean(构造器参数) 都已实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 注意:Spring 并未解决构造器方法中的循环引用问题,要抛异常
}
// 注册依赖关系,确保先销毁被依赖的 bean
registerDependentBean(dep, beanName);
// 递归,获取依赖的 bean
getBean(dep);
}
}
}
if (mbd.isSingleton()) {
// 如果是单例类型(绝大多数都是此类型)
// 再次从缓存中获取,如果仍不存在,则使用传入的 ObjectFactory 创建
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>(
{
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);
}
else if (mbd.isPrototype()) {
// 如果是原型类型,每次都新创建一个
// ...
}
else {
// 如果是其他 scope 类型
// ...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
+
+getSingleton
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 加锁
synchronized (this.singletonObjects) {
// 再次从缓存中获取(和调用前从缓存中获取构成双重校验)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
// 如果正在销毁单例,则抛异常
// 注意:不要在销毁方法中调用获取 bean 方法
}
// 创建前,先注册到正在创建中的集合
// 在出现循环引用时,第二次进入 doGetBean,用此作为判断标志
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// ...
try {
// 使用传入的单例工厂创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 如果异常的出现是因为 bean 被创建了,就忽略异常,否则抛出异常
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
// ...
}
finally {
// ...
// 创建后,从正在创建中集合移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加单例到缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
+
+创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// ...
try {
// 给 Bean 后置处理器一个返回代理的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...
// 常规的创建 Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
+
+doCreateBean
常规的创建 Bean 的具体工作是由 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
39
40
41
42
43
44
45
46
47
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 使用相应的策略创建 bean 实例,例如通过工厂方法或者有参、无参构造器方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// ...
// 使用 ObjectFactory 封装实例并缓存,以解决循环引用问题
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
// 填充属性(包括解析依赖的 bean)
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
// ...
// 如有需要,将 bean 注册为一次性的,以供 beanFactory 在关闭时调用销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// ...
return exposedObject;
}
+
+createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
+
+- 工厂方法
+- 构造器方法
+- 有参
+- 无参
+
+
+
+populateBean
为创建出的实例填充属性,包括解析当前 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
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// ...
// 给 InstantiationAwareBeanPostProcessors 一个机会,
// 在设置 bean 属性前修改 bean 状态,可用于自定义的字段注入
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 是否继续填充属性的流程
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否存在 InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 后置处理 PropertyValues
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 将属性应用到 bean 上(常规情况下,前面的处理都用不上)
applyPropertyValues(beanName, mbd, bw, pvs);
}
+
+initializeBean
在填充完属性后,实例就可以进行初始化工作:
+
+- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息
+- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
+- invokeInitMethods,调用初始化方法
+- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
+
+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
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 处理 Aware 接口的相应方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 应用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
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()) {
// 应用 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
+
+处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
+1
2
3
4
5
6
7
8
9
10
11
12
13
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
+
+调用初始化方法
+- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法
+- 如果自定义 init 方法且满足调用条件,同样进行调用
+
+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
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 是否实现 InitializingBean 接口,是的话调用 afterPropertiesSet 方法
// 给 bean 一个感知属性已设置并做出反应的机会
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean
&& (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 如果存在自定义的 init 方法且方法名称不是 afterPropertiesSet,判断是否调用
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null
&& !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
+
+BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
+
+- 获取 Processor 列表
+- 判断 Processor 类型是否是当前需要的
+- 对 bean 进行处理
+
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
+
+再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
+1
2
3
4
5
6
7
8
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
+
+在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
+
+- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。
+- Bean 自身的初始化。
+
+在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -1701,6 +1541,166 @@
-
+
@@ -1580,7 +1420,7 @@
-
+
@@ -1380,7 +1220,7 @@
-
+
@@ -1147,7 +987,7 @@
-
+
@@ -714,7 +554,7 @@
-
+
@@ -546,7 +386,7 @@
+
+
+
+
+
+
+
@@ -1742,7 +1742,7 @@
Moralok
-
+
diff --git a/leancloud_counter_security_urls.json b/leancloud_counter_security_urls.json
index 881386d7..3857eb32 100644
--- a/leancloud_counter_security_urls.json
+++ b/leancloud_counter_security_urls.json
@@ -1 +1 @@
-[{"title":"在 Ubuntu 上安装 Clash","url":"/2023/05/27/how-to-install-clash-on-ubuntu/"},{"title":"Docker 常用命令列表","url":"/2020/08/19/docker-frequently-used-commands/"},{"title":"在 iOS 和 macOS 上安装 OpenVPN 客户端","url":"/2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/"},{"title":"在 Windows 10 上安装 OpenVPN 服务器","url":"/2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/"},{"title":"使用 OpenVPN 访问家庭内网","url":"/2023/06/07/how-to-use-OpenVPN-to-access-home-network/"},{"title":"Ubuntu server 20.04 安装后没有分配全部磁盘空间","url":"/2023/06/24/Ubuntu-server-20-04-not-all-disk-space-was-allocated-after-installation/"},{"title":"如何使用 SSH 连接 Github 和服务器","url":"/2023/06/28/how-to-use-ssh-to-connect-github-and-server/"},{"title":"Tmux 常用命令和快捷键","url":"/2023/06/29/tmux-frequently-used-commands/"},{"title":"如何为终端、docker 和容器设置代理","url":"/2023/06/13/how-to-configure-proxy-for-terminal-docker-and-container/"},{"title":"如何在 Ubuntu 20.04 上安装 Minikube","url":"/2023/06/23/how-to-install-Minikube-on-Ubuntu-20-04/"},{"title":"JVM GC 的测试和分析","url":"/2023/11/01/testing-and-analysis-of-jvm-gc/"},{"title":"字符串常量池的测试和分析","url":"/2023/11/03/testing-and-analysis-of-StringTable/"},{"title":"Spring Bean 加载过程","url":"/2023/11/17/how-does-Spring-load-beans/"},{"title":"关于 Java 字节码指令的一些例子分析","url":"/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/"},{"title":"基于 Redis 的分布式锁的简单实现","url":"/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/"},{"title":"Java 类加载器源码分析","url":"/2023/07/13/Java-class-loader-source-code-analysis/"},{"title":"JVM 内存区域的测试和分析","url":"/2023/11/04/testing-and-analysis-of-jvm-memory-area/"},{"title":"Java 垃圾收集","url":"/2023/11/07/garbage-collection-in-Java/"}]
\ No newline at end of file
+[{"title":"在 Ubuntu 上安装 Clash","url":"/2023/05/27/how-to-install-clash-on-ubuntu/"},{"title":"在 iOS 和 macOS 上安装 OpenVPN 客户端","url":"/2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/"},{"title":"在 Windows 10 上安装 OpenVPN 服务器","url":"/2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/"},{"title":"使用 OpenVPN 访问家庭内网","url":"/2023/06/07/how-to-use-OpenVPN-to-access-home-network/"},{"title":"如何为终端、docker 和容器设置代理","url":"/2023/06/13/how-to-configure-proxy-for-terminal-docker-and-container/"},{"title":"Docker 常用命令列表","url":"/2020/08/19/docker-frequently-used-commands/"},{"title":"Ubuntu server 20.04 安装后没有分配全部磁盘空间","url":"/2023/06/24/Ubuntu-server-20-04-not-all-disk-space-was-allocated-after-installation/"},{"title":"Tmux 常用命令和快捷键","url":"/2023/06/29/tmux-frequently-used-commands/"},{"title":"如何使用 SSH 连接 Github 和服务器","url":"/2023/06/28/how-to-use-ssh-to-connect-github-and-server/"},{"title":"如何在 Ubuntu 20.04 上安装 Minikube","url":"/2023/06/23/how-to-install-Minikube-on-Ubuntu-20-04/"},{"title":"Spring Bean 加载过程","url":"/2023/08/10/how-does-Spring-load-beans/"},{"title":"JVM GC 的测试和分析","url":"/2023/11/01/testing-and-analysis-of-jvm-gc/"},{"title":"字符串常量池的测试和分析","url":"/2023/11/03/testing-and-analysis-of-StringTable/"},{"title":"Java 类加载器源码分析","url":"/2023/07/13/Java-class-loader-source-code-analysis/"},{"title":"关于 Java 字节码指令的一些例子分析","url":"/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/"},{"title":"基于 Redis 的分布式锁的简单实现","url":"/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/"},{"title":"JVM 内存区域的测试和分析","url":"/2023/11/04/testing-and-analysis-of-jvm-memory-area/"},{"title":"Java 垃圾收集","url":"/2023/11/07/garbage-collection-in-Java/"}]
\ No newline at end of file
diff --git a/page/2/index.html b/page/2/index.html
index 36d9d6ec..ab4a4a4e 100644
--- a/page/2/index.html
+++ b/page/2/index.html
@@ -158,7 +158,7 @@
-
+
@@ -2182,7 +2182,7 @@
-
+
@@ -2028,7 +2028,7 @@
@@ -232,7 +232,7 @@
proxy
+
+ 在 iOS 和 macOS 上安装 OpenVPN 客户端
+ /2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/
+ 安装 OpenVPN Connect
-
+
diff --git a/search.xml b/search.xml
index caf717a6..7947b806 100644
--- a/search.xml
+++ b/search.xml
@@ -45,6 +45,176 @@
-
+
@@ -1151,7 +1151,7 @@
-
+
@@ -1018,7 +1018,7 @@
-
+
@@ -897,7 +897,7 @@
-
+
@@ -781,7 +781,7 @@
-
+
@@ -633,7 +633,7 @@
-
+
@@ -493,7 +493,7 @@
-
+
@@ -343,7 +343,7 @@ macOS 访问官网下载。
iOS 访问 AppStore,需要登录外区 Apple ID。
+配置 OpenVPN Connect
客户端提供了两种方式导入配置文件,一是通过 URL,建议 URL 仅限在私有网络内访问,二是通过其他方式例如邮件,下载为本地文件再导入。
+配置文件的组织方式又分为两种形式,一种是将 CA 根证书 ca.crt,客户端证书 client.crt,客户端密钥 client.key 的内容复制粘贴到 client.ovpn 中,形成一个联合配置文件;另一种是使用 openssl 将 CA 根证书 ca.crt,客户端证书 client.crt,客户端密钥 client.key 转换为 PKCS#12 文件,先后导入 client.ovpn12 和 client.ovpn。
+单一 client.ovpn
从目录 C:\Program Files\OpenVPN\sample-config
复制客户端配置文件模板 client.ovpn,修改以下配置:
+remote your-server 1194
;ca ca.crt
;cert client.crt
;key client.key
;tls-auth ta.key 1
<ca>
-----BEGIN CERTIFICATE-----
paste contents of ca.crt
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
paste contents of client.crt
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
paste contents of client.key
-----END PRIVATE KEY-----
</key>
+将 remote your-server 1194
中的地址和端口替换成你的 OpenVPN server 的地址和端口。将 ca ca.crt
, cert client.crt
, key client.key
, tls-auth ta.key 1
注释掉,将各自文件中的内容以上述类 XML 的形式粘贴到 client.ovpn 中。
+将修改好的客户端配置文件导入到客户端中即可。
+client.ovpn + client.opvn12
使用 openssl 命令将客户端的证书和私钥文件转换为 PKCS#12 形式的文件。该命令会提示 Enter Export Password
,可以为空,但为了安全建议设置密码。
+openssl pkcs12 -export -in cert -inkey key -certfile ca -name MyClient -out client.ovpn12
+由于在 iOS 中导入 PKCS#12 文件到 Keychain 中时只导入了客户端证书和密钥,CA 根证书并没有导入,client.ovpn 文件中必须要保留 CA 根证书的配置。
既可以用传统的引用文件的方式:
+ca ca.crt
+也可以用类 XML 的形式粘贴 ca.crt 内容到 client.ovpn 中:
+<ca>
paste contents of ca.crt here
</ca>
+先导入 client.ovpn12(需要输入转换时的密码),再导入 client.ovpn。
+
+但是我失败了……导入 client.ovpn12 时密码一直错误,搜索到类似的案例,但是没有找到解决方案。不确定是不是 openssl 版本引起的。
+
+路由器 NAT
在路由器管理后台的 NAT 设置功能里,配置好对外端口号和 Windows 10 主机上 OpenVPN 端口号的映射关系。
+参考链接
iOS 使用 OpenVPN 的 FAQ
如何通过 iOS Keychain 使用客户端证书和密钥
如何配置 iOS OpenVPN 客户端的证书认证
+]]>
+
+ openvpn
+
+
+
+ 在 Windows 10 上安装 OpenVPN 服务器
+ /2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/
+ 安装 OpenVPN server
@@ -191,166 +191,6 @@
@@ -203,26 +203,6 @@
@@ -203,26 +203,6 @@
-
+
@@ -359,9 +359,6 @@ 从 OpenVPN 社区 下载 Windows 64-bit MSI installer。本次安装的版本为 OpenVPN 2.6.4。
+
+注意事项:在选择安装类型时选择 Customize 而不要选择 Install Now。额外勾选 OpenVPN -> OpenVPN Service -> Entire feature will be installed on local hard drive 和 OpenSSL Utilities -> EasyRSA 3 Certificate Management Scripts -> Entire feature will be installed on local hard drive。
+
+安装完毕后,会弹出一条消息提示未找到可读的连接配置文件,暂时忽略。
此时在 控制面板\网络和 Internet\网络连接 中可以看到创建了两个新的网络适配器 OpenVPN TAP-Windows6 和 OpenVPN Wintun。
+配置 OpenVPN server
打开 Windows 10 终端程序。
进入 OpenVPN 默认安装目录中的 easy-rsa 目录。
+cd 'C:\Program Files\OpenVPN\easy-rsa'
+执行命令进入 Easy-RSA 3 Shell
+.\EasyRSA-Start.bat
+初始化公钥基础设施目录 pki
+./easyrsa init-pki
+构建证书颁发机构(CA)密钥,CA 根证书文件将在后续用于对其他证书和密钥进行签名。该命令要求输入 Common Name,输入主机名即可。创建的 ca.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki
中,ca.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
+./easyrsa build-ca nopass
+构建服务器证书和密钥。创建的 server.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\issued
中,server.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
+./easyrsa build-server-full server nopass
+构建客户端证书和密钥。创建的 client.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\issued
中,client.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
+./easyrsa build-client-full client nopass
+生成 Diffie-Hellman 参数
+./easyrsa gen-dh
+从目录 C:\Program Files\OpenVPN\sample-config
复制服务端配置文件模板 server.ovpn 到目录 C:\Program Files\OpenVPN\config
中,修改以下配置:
+port 1194
dh dh.pem
duplicate-cn
;tls-auth ta.key 0
+端口号按需修改,默认为1194,需要保证 OpenVPN 的网络流量可以通过防火墙,设置 Windows 10 Defender 允许 OpenVPN 通过即可。dh2048.pem 修改为生成的文件名 dh.pem。取消注释 duplicate-cn,让多个客户端使用同一个客户端证书。注释掉 tls-auth ta.key 0。复制 ca.crt,dh.pem,server.crt 和 server.key 到目录 C:\Program Files\OpenVPN\config 中。
+启动与连接
启动 OpenVPN,点击连接,系统提示分配 IP 10.8.0.1。按配置,每次 OpenVPN server 都将为自己分配 10.8.0.1。
+参考链接
openvpn安装配置说明(windows系统)
如何在Windows 10上安装和配置OpenVPN
+]]>
+
+ openvpn
+
+
+
+ 使用 OpenVPN 访问家庭内网
+ /2023/06/07/how-to-use-OpenVPN-to-access-home-network/
+ 网络概况
diff --git a/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html b/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html
index 9bff8d7e..f765d3b9 100644
--- a/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html
+++ b/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/index.html
@@ -33,7 +33,7 @@
-
+
@@ -170,7 +170,7 @@
@@ -245,7 +245,7 @@
-
+
@@ -355,7 +355,7 @@
-
- Spring Bean 加载过程
-
diff --git a/archives/2020/08/index.html b/archives/2020/08/index.html
index 5cb2fa4a..9a8aec9a 100644
--- a/archives/2020/08/index.html
+++ b/archives/2020/08/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2020/index.html b/archives/2020/index.html
index 4c74ba98..18e0f275 100644
--- a/archives/2020/index.html
+++ b/archives/2020/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/05/index.html b/archives/2023/05/index.html
index 539bcf0e..183b92da 100644
--- a/archives/2023/05/index.html
+++ b/archives/2023/05/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/06/index.html b/archives/2023/06/index.html
index be634e2c..5272063f 100644
--- a/archives/2023/06/index.html
+++ b/archives/2023/06/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/archives/2023/07/index.html b/archives/2023/07/index.html
index 7f1c535f..1cb43f2f 100644
--- a/archives/2023/07/index.html
+++ b/archives/2023/07/index.html
@@ -158,7 +158,7 @@ Moralok
diff --git a/tags/Java/index.html b/archives/2023/08/index.html
similarity index 70%
rename from tags/Java/index.html
rename to archives/2023/08/index.html
index 94638b7d..4aa36998 100644
--- a/tags/Java/index.html
+++ b/archives/2023/08/index.html
@@ -22,7 +22,7 @@
-
+
@@ -30,14 +30,14 @@
-
+
-
+
-标签: Java | Moralok
+归档 | Moralok
@@ -68,7 +68,7 @@
- Moralok
+ Moralok
@@ -158,7 +158,7 @@
@@ -186,7 +186,7 @@
-
+
@@ -195,9 +195,7 @@
- Java
- 标签
-
+ 嗯..! 目前共计 18 篇日志。 继续努力。
@@ -209,15 +207,15 @@ Java
@@ -225,105 +223,6 @@ Java
-
-
-
-
- Java 垃圾收集
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 字符串常量池的测试和分析
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/archives/2023/11/index.html b/archives/2023/11/index.html
index 38cea205..ece70fec 100644
--- a/archives/2023/11/index.html
+++ b/archives/2023/11/index.html
@@ -158,7 +158,7 @@ Moralok
@@ -203,26 +203,6 @@ Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
2023
-
-
-
-
-
-
-
-
-
-
Moralok
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Spring Bean 加载过程
-
-
-
-
-
-
-
-
-
- Spring Bean 生命周期
-
-获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
-1
2
3
4
public Object getBean(String name) throws BeansException {
// 具体工作由 doGetBean 完成
return doGetBean(name, null, null, false);
}
-
-deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
-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
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换名称:去除 FactoryBean 的前缀 &,将别名转换为规范名称
final String beanName = transformedBeanName(name);
Object bean;
// 检查单例缓存中是否已存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
// 如果已存在,直接返回该实例或者使用该实例(FactoryBean)创建并返回对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果当前 Bean 是一个正在创建中的 prototype 类型,表明可能发生循环引用
// 注意:Spring 并未解决 prototype 类型的循环引用问题,要抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果当前 beanFactory 没有 bean 定义,去 parent beanFactory 中查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 标记为至少创建过一次
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保 bean 依赖的 bean(构造器参数) 都已实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 注意:Spring 并未解决构造器方法中的循环引用问题,要抛异常
}
// 注册依赖关系,确保先销毁被依赖的 bean
registerDependentBean(dep, beanName);
// 递归,获取依赖的 bean
getBean(dep);
}
}
}
if (mbd.isSingleton()) {
// 如果是单例类型(绝大多数都是此类型)
// 再次从缓存中获取,如果仍不存在,则使用传入的 ObjectFactory 创建
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>(
{
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);
}
else if (mbd.isPrototype()) {
// 如果是原型类型,每次都新创建一个
// ...
}
else {
// 如果是其他 scope 类型
// ...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
-
-getSingleton
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 加锁
synchronized (this.singletonObjects) {
// 再次从缓存中获取(和调用前从缓存中获取构成双重校验)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
// 如果正在销毁单例,则抛异常
// 注意:不要在销毁方法中调用获取 bean 方法
}
// 创建前,先注册到正在创建中的集合
// 在出现循环引用时,第二次进入 doGetBean,用此作为判断标志
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// ...
try {
// 使用传入的单例工厂创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 如果异常的出现是因为 bean 被创建了,就忽略异常,否则抛出异常
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
// ...
}
finally {
// ...
// 创建后,从正在创建中集合移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加单例到缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
-
-创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
-1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// ...
try {
// 给 Bean 后置处理器一个返回代理的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...
// 常规的创建 Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
-
-doCreateBean
常规的创建 Bean 的具体工作是由 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
39
40
41
42
43
44
45
46
47
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 使用相应的策略创建 bean 实例,例如通过工厂方法或者有参、无参构造器方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// ...
// 使用 ObjectFactory 封装实例并缓存,以解决循环引用问题
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
// 填充属性(包括解析依赖的 bean)
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
// ...
// 如有需要,将 bean 注册为一次性的,以供 beanFactory 在关闭时调用销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// ...
return exposedObject;
}
-
-createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
-
-- 工厂方法
-- 构造器方法
-- 有参
-- 无参
-
-
-
-populateBean
为创建出的实例填充属性,包括解析当前 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
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// ...
// 给 InstantiationAwareBeanPostProcessors 一个机会,
// 在设置 bean 属性前修改 bean 状态,可用于自定义的字段注入
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 是否继续填充属性的流程
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否存在 InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 后置处理 PropertyValues
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 将属性应用到 bean 上(常规情况下,前面的处理都用不上)
applyPropertyValues(beanName, mbd, bw, pvs);
}
-
-initializeBean
在填充完属性后,实例就可以进行初始化工作:
-
-- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息
-- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
-- invokeInitMethods,调用初始化方法
-- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
-
-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
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 处理 Aware 接口的相应方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 应用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
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()) {
// 应用 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
-
-处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
-1
2
3
4
5
6
7
8
9
10
11
12
13
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
-
-调用初始化方法
-- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法
-- 如果自定义 init 方法且满足调用条件,同样进行调用
-
-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
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 是否实现 InitializingBean 接口,是的话调用 afterPropertiesSet 方法
// 给 bean 一个感知属性已设置并做出反应的机会
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean
&& (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 如果存在自定义的 init 方法且方法名称不是 afterPropertiesSet,判断是否调用
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null
&& !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
-
-BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
-
-- 获取 Processor 列表
-- 判断 Processor 类型是否是当前需要的
-- 对 bean 进行处理
-
-1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
-
-再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
-1
2
3
4
5
6
7
8
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
-
-在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
-
-- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。
-- Bean 自身的初始化。
-
-在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -392,7 +232,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Spring Bean 加载过程
+
+
+
+
+
+
+
+
+
+ Spring Bean 生命周期
+
+获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
+1
2
3
4
public Object getBean(String name) throws BeansException {
// 具体工作由 doGetBean 完成
return doGetBean(name, null, null, false);
}
+
+deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
+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
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换名称:去除 FactoryBean 的前缀 &,将别名转换为规范名称
final String beanName = transformedBeanName(name);
Object bean;
// 检查单例缓存中是否已存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
// 如果已存在,直接返回该实例或者使用该实例(FactoryBean)创建并返回对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果当前 Bean 是一个正在创建中的 prototype 类型,表明可能发生循环引用
// 注意:Spring 并未解决 prototype 类型的循环引用问题,要抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果当前 beanFactory 没有 bean 定义,去 parent beanFactory 中查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 标记为至少创建过一次
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保 bean 依赖的 bean(构造器参数) 都已实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 注意:Spring 并未解决构造器方法中的循环引用问题,要抛异常
}
// 注册依赖关系,确保先销毁被依赖的 bean
registerDependentBean(dep, beanName);
// 递归,获取依赖的 bean
getBean(dep);
}
}
}
if (mbd.isSingleton()) {
// 如果是单例类型(绝大多数都是此类型)
// 再次从缓存中获取,如果仍不存在,则使用传入的 ObjectFactory 创建
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>(
{
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);
}
else if (mbd.isPrototype()) {
// 如果是原型类型,每次都新创建一个
// ...
}
else {
// 如果是其他 scope 类型
// ...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
+
+getSingleton
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 加锁
synchronized (this.singletonObjects) {
// 再次从缓存中获取(和调用前从缓存中获取构成双重校验)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
// 如果正在销毁单例,则抛异常
// 注意:不要在销毁方法中调用获取 bean 方法
}
// 创建前,先注册到正在创建中的集合
// 在出现循环引用时,第二次进入 doGetBean,用此作为判断标志
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// ...
try {
// 使用传入的单例工厂创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 如果异常的出现是因为 bean 被创建了,就忽略异常,否则抛出异常
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
// ...
}
finally {
// ...
// 创建后,从正在创建中集合移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加单例到缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
+
+创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// ...
try {
// 给 Bean 后置处理器一个返回代理的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...
// 常规的创建 Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
+
+doCreateBean
常规的创建 Bean 的具体工作是由 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
39
40
41
42
43
44
45
46
47
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 使用相应的策略创建 bean 实例,例如通过工厂方法或者有参、无参构造器方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// ...
// 使用 ObjectFactory 封装实例并缓存,以解决循环引用问题
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
// 填充属性(包括解析依赖的 bean)
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
// ...
// 如有需要,将 bean 注册为一次性的,以供 beanFactory 在关闭时调用销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// ...
return exposedObject;
}
+
+createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
+
+- 工厂方法
+- 构造器方法
+- 有参
+- 无参
+
+
+
+populateBean
为创建出的实例填充属性,包括解析当前 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
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// ...
// 给 InstantiationAwareBeanPostProcessors 一个机会,
// 在设置 bean 属性前修改 bean 状态,可用于自定义的字段注入
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 是否继续填充属性的流程
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否存在 InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 后置处理 PropertyValues
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 将属性应用到 bean 上(常规情况下,前面的处理都用不上)
applyPropertyValues(beanName, mbd, bw, pvs);
}
+
+initializeBean
在填充完属性后,实例就可以进行初始化工作:
+
+- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息
+- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
+- invokeInitMethods,调用初始化方法
+- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
+
+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
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 处理 Aware 接口的相应方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 应用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
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()) {
// 应用 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
+
+处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
+1
2
3
4
5
6
7
8
9
10
11
12
13
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
+
+调用初始化方法
+- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法
+- 如果自定义 init 方法且满足调用条件,同样进行调用
+
+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
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 是否实现 InitializingBean 接口,是的话调用 afterPropertiesSet 方法
// 给 bean 一个感知属性已设置并做出反应的机会
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean
&& (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 如果存在自定义的 init 方法且方法名称不是 afterPropertiesSet,判断是否调用
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null
&& !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
+
+BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
+
+- 获取 Processor 列表
+- 判断 Processor 类型是否是当前需要的
+- 对 bean 进行处理
+
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
+
+再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
+1
2
3
4
5
6
7
8
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
+
+在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
+
+- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。
+- Bean 自身的初始化。
+
+在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -1701,6 +1541,166 @@
-
+
@@ -1580,7 +1420,7 @@
-
+
@@ -1380,7 +1220,7 @@
-
+
@@ -1147,7 +987,7 @@
-
+
@@ -714,7 +554,7 @@
-
+
@@ -546,7 +386,7 @@
+
+
+
+
+
+
+
@@ -1742,7 +1742,7 @@
Moralok
-
+
diff --git a/leancloud_counter_security_urls.json b/leancloud_counter_security_urls.json
index 881386d7..3857eb32 100644
--- a/leancloud_counter_security_urls.json
+++ b/leancloud_counter_security_urls.json
@@ -1 +1 @@
-[{"title":"在 Ubuntu 上安装 Clash","url":"/2023/05/27/how-to-install-clash-on-ubuntu/"},{"title":"Docker 常用命令列表","url":"/2020/08/19/docker-frequently-used-commands/"},{"title":"在 iOS 和 macOS 上安装 OpenVPN 客户端","url":"/2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/"},{"title":"在 Windows 10 上安装 OpenVPN 服务器","url":"/2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/"},{"title":"使用 OpenVPN 访问家庭内网","url":"/2023/06/07/how-to-use-OpenVPN-to-access-home-network/"},{"title":"Ubuntu server 20.04 安装后没有分配全部磁盘空间","url":"/2023/06/24/Ubuntu-server-20-04-not-all-disk-space-was-allocated-after-installation/"},{"title":"如何使用 SSH 连接 Github 和服务器","url":"/2023/06/28/how-to-use-ssh-to-connect-github-and-server/"},{"title":"Tmux 常用命令和快捷键","url":"/2023/06/29/tmux-frequently-used-commands/"},{"title":"如何为终端、docker 和容器设置代理","url":"/2023/06/13/how-to-configure-proxy-for-terminal-docker-and-container/"},{"title":"如何在 Ubuntu 20.04 上安装 Minikube","url":"/2023/06/23/how-to-install-Minikube-on-Ubuntu-20-04/"},{"title":"JVM GC 的测试和分析","url":"/2023/11/01/testing-and-analysis-of-jvm-gc/"},{"title":"字符串常量池的测试和分析","url":"/2023/11/03/testing-and-analysis-of-StringTable/"},{"title":"Spring Bean 加载过程","url":"/2023/11/17/how-does-Spring-load-beans/"},{"title":"关于 Java 字节码指令的一些例子分析","url":"/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/"},{"title":"基于 Redis 的分布式锁的简单实现","url":"/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/"},{"title":"Java 类加载器源码分析","url":"/2023/07/13/Java-class-loader-source-code-analysis/"},{"title":"JVM 内存区域的测试和分析","url":"/2023/11/04/testing-and-analysis-of-jvm-memory-area/"},{"title":"Java 垃圾收集","url":"/2023/11/07/garbage-collection-in-Java/"}]
\ No newline at end of file
+[{"title":"在 Ubuntu 上安装 Clash","url":"/2023/05/27/how-to-install-clash-on-ubuntu/"},{"title":"在 iOS 和 macOS 上安装 OpenVPN 客户端","url":"/2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/"},{"title":"在 Windows 10 上安装 OpenVPN 服务器","url":"/2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/"},{"title":"使用 OpenVPN 访问家庭内网","url":"/2023/06/07/how-to-use-OpenVPN-to-access-home-network/"},{"title":"如何为终端、docker 和容器设置代理","url":"/2023/06/13/how-to-configure-proxy-for-terminal-docker-and-container/"},{"title":"Docker 常用命令列表","url":"/2020/08/19/docker-frequently-used-commands/"},{"title":"Ubuntu server 20.04 安装后没有分配全部磁盘空间","url":"/2023/06/24/Ubuntu-server-20-04-not-all-disk-space-was-allocated-after-installation/"},{"title":"Tmux 常用命令和快捷键","url":"/2023/06/29/tmux-frequently-used-commands/"},{"title":"如何使用 SSH 连接 Github 和服务器","url":"/2023/06/28/how-to-use-ssh-to-connect-github-and-server/"},{"title":"如何在 Ubuntu 20.04 上安装 Minikube","url":"/2023/06/23/how-to-install-Minikube-on-Ubuntu-20-04/"},{"title":"Spring Bean 加载过程","url":"/2023/08/10/how-does-Spring-load-beans/"},{"title":"JVM GC 的测试和分析","url":"/2023/11/01/testing-and-analysis-of-jvm-gc/"},{"title":"字符串常量池的测试和分析","url":"/2023/11/03/testing-and-analysis-of-StringTable/"},{"title":"Java 类加载器源码分析","url":"/2023/07/13/Java-class-loader-source-code-analysis/"},{"title":"关于 Java 字节码指令的一些例子分析","url":"/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/"},{"title":"基于 Redis 的分布式锁的简单实现","url":"/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/"},{"title":"JVM 内存区域的测试和分析","url":"/2023/11/04/testing-and-analysis-of-jvm-memory-area/"},{"title":"Java 垃圾收集","url":"/2023/11/07/garbage-collection-in-Java/"}]
\ No newline at end of file
diff --git a/page/2/index.html b/page/2/index.html
index 36d9d6ec..ab4a4a4e 100644
--- a/page/2/index.html
+++ b/page/2/index.html
@@ -158,7 +158,7 @@
-
+
@@ -2182,7 +2182,7 @@
-
+
@@ -2028,7 +2028,7 @@
@@ -232,7 +232,7 @@
proxy
+
+ 在 iOS 和 macOS 上安装 OpenVPN 客户端
+ /2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/
+ 安装 OpenVPN Connect
-
+
diff --git a/search.xml b/search.xml
index caf717a6..7947b806 100644
--- a/search.xml
+++ b/search.xml
@@ -45,6 +45,176 @@
-
+
@@ -1151,7 +1151,7 @@
-
+
@@ -1018,7 +1018,7 @@
-
+
@@ -897,7 +897,7 @@
-
+
@@ -781,7 +781,7 @@
-
+
@@ -633,7 +633,7 @@
-
+
@@ -493,7 +493,7 @@
-
+
@@ -343,7 +343,7 @@ macOS 访问官网下载。
iOS 访问 AppStore,需要登录外区 Apple ID。
+配置 OpenVPN Connect
客户端提供了两种方式导入配置文件,一是通过 URL,建议 URL 仅限在私有网络内访问,二是通过其他方式例如邮件,下载为本地文件再导入。
+配置文件的组织方式又分为两种形式,一种是将 CA 根证书 ca.crt,客户端证书 client.crt,客户端密钥 client.key 的内容复制粘贴到 client.ovpn 中,形成一个联合配置文件;另一种是使用 openssl 将 CA 根证书 ca.crt,客户端证书 client.crt,客户端密钥 client.key 转换为 PKCS#12 文件,先后导入 client.ovpn12 和 client.ovpn。
+单一 client.ovpn
从目录 C:\Program Files\OpenVPN\sample-config
复制客户端配置文件模板 client.ovpn,修改以下配置:
+remote your-server 1194
;ca ca.crt
;cert client.crt
;key client.key
;tls-auth ta.key 1
<ca>
-----BEGIN CERTIFICATE-----
paste contents of ca.crt
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
paste contents of client.crt
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
paste contents of client.key
-----END PRIVATE KEY-----
</key>
+将 remote your-server 1194
中的地址和端口替换成你的 OpenVPN server 的地址和端口。将 ca ca.crt
, cert client.crt
, key client.key
, tls-auth ta.key 1
注释掉,将各自文件中的内容以上述类 XML 的形式粘贴到 client.ovpn 中。
+将修改好的客户端配置文件导入到客户端中即可。
+client.ovpn + client.opvn12
使用 openssl 命令将客户端的证书和私钥文件转换为 PKCS#12 形式的文件。该命令会提示 Enter Export Password
,可以为空,但为了安全建议设置密码。
+openssl pkcs12 -export -in cert -inkey key -certfile ca -name MyClient -out client.ovpn12
+由于在 iOS 中导入 PKCS#12 文件到 Keychain 中时只导入了客户端证书和密钥,CA 根证书并没有导入,client.ovpn 文件中必须要保留 CA 根证书的配置。
既可以用传统的引用文件的方式:
+ca ca.crt
+也可以用类 XML 的形式粘贴 ca.crt 内容到 client.ovpn 中:
+<ca>
paste contents of ca.crt here
</ca>
+先导入 client.ovpn12(需要输入转换时的密码),再导入 client.ovpn。
+
+但是我失败了……导入 client.ovpn12 时密码一直错误,搜索到类似的案例,但是没有找到解决方案。不确定是不是 openssl 版本引起的。
+
+路由器 NAT
在路由器管理后台的 NAT 设置功能里,配置好对外端口号和 Windows 10 主机上 OpenVPN 端口号的映射关系。
+参考链接
iOS 使用 OpenVPN 的 FAQ
如何通过 iOS Keychain 使用客户端证书和密钥
如何配置 iOS OpenVPN 客户端的证书认证
+]]>
+
+ openvpn
+
+
+
+ 在 Windows 10 上安装 OpenVPN 服务器
+ /2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/
+ 安装 OpenVPN server
@@ -191,166 +191,6 @@
@@ -203,26 +203,6 @@
@@ -203,26 +203,6 @@
-
+
@@ -359,9 +359,6 @@ Moralok
diff --git a/archives/2020/index.html b/archives/2020/index.html index 4c74ba98..18e0f275 100644 --- a/archives/2020/index.html +++ b/archives/2020/index.html @@ -158,7 +158,7 @@Moralok
diff --git a/archives/2023/05/index.html b/archives/2023/05/index.html index 539bcf0e..183b92da 100644 --- a/archives/2023/05/index.html +++ b/archives/2023/05/index.html @@ -158,7 +158,7 @@Moralok
diff --git a/archives/2023/06/index.html b/archives/2023/06/index.html index be634e2c..5272063f 100644 --- a/archives/2023/06/index.html +++ b/archives/2023/06/index.html @@ -158,7 +158,7 @@Moralok
diff --git a/archives/2023/07/index.html b/archives/2023/07/index.html index 7f1c535f..1cb43f2f 100644 --- a/archives/2023/07/index.html +++ b/archives/2023/07/index.html @@ -158,7 +158,7 @@Moralok
diff --git a/tags/Java/index.html b/archives/2023/08/index.html similarity index 70% rename from tags/Java/index.html rename to archives/2023/08/index.html index 94638b7d..4aa36998 100644 --- a/tags/Java/index.html +++ b/archives/2023/08/index.html @@ -22,7 +22,7 @@ - + @@ -30,14 +30,14 @@ - + - + -Moralok
+Moralok
@@ -158,7 +158,7 @@ @@ -186,7 +186,7 @@ -Java - 标签 -
+ 嗯..! 目前共计 18 篇日志。 继续努力。Java
@@ -225,105 +223,6 @@ Java
-
-
-
-
- Java 垃圾收集
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 字符串常量池的测试和分析
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Java
Moralok
Moralok
2023Moralok
2023 -Moralok
2023 -Moralok
-- Spring Bean 加载过程 -
- - -Spring Bean 生命周期
- -获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
1 | public Object getBean(String name) throws BeansException { |
deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
-1 | protected <T> T doGetBean( |
getSingleton
1 | public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { |
创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
-1 | protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { |
doCreateBean
常规的创建 Bean 的具体工作是由 doCreateBean 完成的。
-1 | protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException { |
createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
--
-
- 工厂方法 -
- 构造器方法
-
-
- 有参 -
- 无参 -
-
populateBean
为创建出的实例填充属性,包括解析当前 bean 所依赖的 bean。
-1 | protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { |
initializeBean
在填充完属性后,实例就可以进行初始化工作:
--
-
- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息 -
- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法 -
- invokeInitMethods,调用初始化方法 -
- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法 -
1 | protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { |
处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
-1 | private void invokeAwareMethods(final String beanName, final Object bean) { |
调用初始化方法
-
-
- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法 -
- 如果自定义 init 方法且满足调用条件,同样进行调用 -
1 | protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { |
BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
--
-
- 获取 Processor 列表 -
- 判断 Processor 类型是否是当前需要的 -
- 对 bean 进行处理 -
1 | public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { |
再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
1 | // Initialize the bean instance. |
在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
--
-
- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。 -
- Bean 自身的初始化。 -
在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Spring Bean 加载过程
+
+
+
+
+
+
+
+
+
+ Spring Bean 生命周期
+
+获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
+1
2
3
4
public Object getBean(String name) throws BeansException {
// 具体工作由 doGetBean 完成
return doGetBean(name, null, null, false);
}
+
+deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
+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
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换名称:去除 FactoryBean 的前缀 &,将别名转换为规范名称
final String beanName = transformedBeanName(name);
Object bean;
// 检查单例缓存中是否已存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
// 如果已存在,直接返回该实例或者使用该实例(FactoryBean)创建并返回对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果当前 Bean 是一个正在创建中的 prototype 类型,表明可能发生循环引用
// 注意:Spring 并未解决 prototype 类型的循环引用问题,要抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果当前 beanFactory 没有 bean 定义,去 parent beanFactory 中查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 标记为至少创建过一次
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保 bean 依赖的 bean(构造器参数) 都已实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 注意:Spring 并未解决构造器方法中的循环引用问题,要抛异常
}
// 注册依赖关系,确保先销毁被依赖的 bean
registerDependentBean(dep, beanName);
// 递归,获取依赖的 bean
getBean(dep);
}
}
}
if (mbd.isSingleton()) {
// 如果是单例类型(绝大多数都是此类型)
// 再次从缓存中获取,如果仍不存在,则使用传入的 ObjectFactory 创建
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>(
{
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);
}
else if (mbd.isPrototype()) {
// 如果是原型类型,每次都新创建一个
// ...
}
else {
// 如果是其他 scope 类型
// ...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
+
+getSingleton
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 加锁
synchronized (this.singletonObjects) {
// 再次从缓存中获取(和调用前从缓存中获取构成双重校验)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
// 如果正在销毁单例,则抛异常
// 注意:不要在销毁方法中调用获取 bean 方法
}
// 创建前,先注册到正在创建中的集合
// 在出现循环引用时,第二次进入 doGetBean,用此作为判断标志
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// ...
try {
// 使用传入的单例工厂创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 如果异常的出现是因为 bean 被创建了,就忽略异常,否则抛出异常
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
// ...
}
finally {
// ...
// 创建后,从正在创建中集合移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加单例到缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
+
+创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// ...
try {
// 给 Bean 后置处理器一个返回代理的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...
// 常规的创建 Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
+
+doCreateBean
常规的创建 Bean 的具体工作是由 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
39
40
41
42
43
44
45
46
47
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 使用相应的策略创建 bean 实例,例如通过工厂方法或者有参、无参构造器方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// ...
// 使用 ObjectFactory 封装实例并缓存,以解决循环引用问题
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
// 填充属性(包括解析依赖的 bean)
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
// ...
// 如有需要,将 bean 注册为一次性的,以供 beanFactory 在关闭时调用销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// ...
return exposedObject;
}
+
+createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
+
+- 工厂方法
+- 构造器方法
+- 有参
+- 无参
+
+
+
+populateBean
为创建出的实例填充属性,包括解析当前 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
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// ...
// 给 InstantiationAwareBeanPostProcessors 一个机会,
// 在设置 bean 属性前修改 bean 状态,可用于自定义的字段注入
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 是否继续填充属性的流程
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否存在 InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 后置处理 PropertyValues
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 将属性应用到 bean 上(常规情况下,前面的处理都用不上)
applyPropertyValues(beanName, mbd, bw, pvs);
}
+
+initializeBean
在填充完属性后,实例就可以进行初始化工作:
+
+- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息
+- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
+- invokeInitMethods,调用初始化方法
+- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
+
+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
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 处理 Aware 接口的相应方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 应用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
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()) {
// 应用 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
+
+处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
+1
2
3
4
5
6
7
8
9
10
11
12
13
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
+
+调用初始化方法
+- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法
+- 如果自定义 init 方法且满足调用条件,同样进行调用
+
+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
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 是否实现 InitializingBean 接口,是的话调用 afterPropertiesSet 方法
// 给 bean 一个感知属性已设置并做出反应的机会
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean
&& (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 如果存在自定义的 init 方法且方法名称不是 afterPropertiesSet,判断是否调用
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null
&& !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
+
+BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
+
+- 获取 Processor 列表
+- 判断 Processor 类型是否是当前需要的
+- 对 bean 进行处理
+
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
+
+再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
+1
2
3
4
5
6
7
8
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
+
+在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
+
+- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。
+- Bean 自身的初始化。
+
+在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -1701,6 +1541,166 @@
-
+
@@ -1580,7 +1420,7 @@
-
+
@@ -1380,7 +1220,7 @@
-
+
@@ -1147,7 +987,7 @@
-
+
@@ -714,7 +554,7 @@
-
+
@@ -546,7 +386,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Spring Bean 加载过程
+
+
+
+
+
+
+
+
+
+ Spring Bean 生命周期
+
+获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
+1
2
3
4
public Object getBean(String name) throws BeansException {
// 具体工作由 doGetBean 完成
return doGetBean(name, null, null, false);
}
+
+deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
+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
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换名称:去除 FactoryBean 的前缀 &,将别名转换为规范名称
final String beanName = transformedBeanName(name);
Object bean;
// 检查单例缓存中是否已存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
// 如果已存在,直接返回该实例或者使用该实例(FactoryBean)创建并返回对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果当前 Bean 是一个正在创建中的 prototype 类型,表明可能发生循环引用
// 注意:Spring 并未解决 prototype 类型的循环引用问题,要抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果当前 beanFactory 没有 bean 定义,去 parent beanFactory 中查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 标记为至少创建过一次
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保 bean 依赖的 bean(构造器参数) 都已实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 注意:Spring 并未解决构造器方法中的循环引用问题,要抛异常
}
// 注册依赖关系,确保先销毁被依赖的 bean
registerDependentBean(dep, beanName);
// 递归,获取依赖的 bean
getBean(dep);
}
}
}
if (mbd.isSingleton()) {
// 如果是单例类型(绝大多数都是此类型)
// 再次从缓存中获取,如果仍不存在,则使用传入的 ObjectFactory 创建
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>(
{
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);
}
else if (mbd.isPrototype()) {
// 如果是原型类型,每次都新创建一个
// ...
}
else {
// 如果是其他 scope 类型
// ...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
+
+getSingleton
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 加锁
synchronized (this.singletonObjects) {
// 再次从缓存中获取(和调用前从缓存中获取构成双重校验)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
// 如果正在销毁单例,则抛异常
// 注意:不要在销毁方法中调用获取 bean 方法
}
// 创建前,先注册到正在创建中的集合
// 在出现循环引用时,第二次进入 doGetBean,用此作为判断标志
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// ...
try {
// 使用传入的单例工厂创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 如果异常的出现是因为 bean 被创建了,就忽略异常,否则抛出异常
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
// ...
}
finally {
// ...
// 创建后,从正在创建中集合移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加单例到缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
+
+创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// ...
try {
// 给 Bean 后置处理器一个返回代理的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...
// 常规的创建 Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
+
+doCreateBean
常规的创建 Bean 的具体工作是由 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
39
40
41
42
43
44
45
46
47
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 使用相应的策略创建 bean 实例,例如通过工厂方法或者有参、无参构造器方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// ...
// 使用 ObjectFactory 封装实例并缓存,以解决循环引用问题
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
// 填充属性(包括解析依赖的 bean)
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
// ...
// 如有需要,将 bean 注册为一次性的,以供 beanFactory 在关闭时调用销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// ...
return exposedObject;
}
+
+createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
+
+- 工厂方法
+- 构造器方法
+- 有参
+- 无参
+
+
+
+populateBean
为创建出的实例填充属性,包括解析当前 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
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// ...
// 给 InstantiationAwareBeanPostProcessors 一个机会,
// 在设置 bean 属性前修改 bean 状态,可用于自定义的字段注入
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 是否继续填充属性的流程
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否存在 InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 后置处理 PropertyValues
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 将属性应用到 bean 上(常规情况下,前面的处理都用不上)
applyPropertyValues(beanName, mbd, bw, pvs);
}
+
+initializeBean
在填充完属性后,实例就可以进行初始化工作:
+
+- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息
+- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
+- invokeInitMethods,调用初始化方法
+- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
+
+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
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 处理 Aware 接口的相应方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 应用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
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()) {
// 应用 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
+
+处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
+1
2
3
4
5
6
7
8
9
10
11
12
13
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
+
+调用初始化方法
+- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法
+- 如果自定义 init 方法且满足调用条件,同样进行调用
+
+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
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 是否实现 InitializingBean 接口,是的话调用 afterPropertiesSet 方法
// 给 bean 一个感知属性已设置并做出反应的机会
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean
&& (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 如果存在自定义的 init 方法且方法名称不是 afterPropertiesSet,判断是否调用
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null
&& !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
+
+BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
+
+- 获取 Processor 列表
+- 判断 Processor 类型是否是当前需要的
+- 对 bean 进行处理
+
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
+
+再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
+1
2
3
4
5
6
7
8
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
+
+在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
+
+- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。
+- Bean 自身的初始化。
+
+在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -1701,6 +1541,166 @@
-
+
@@ -1580,7 +1420,7 @@
-
+
@@ -1380,7 +1220,7 @@
-
+
@@ -1147,7 +987,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Spring Bean 加载过程
+
+
+
+
+
+
+
+
+
+ Spring Bean 生命周期
+
+获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
+1
2
3
4
public Object getBean(String name) throws BeansException {
// 具体工作由 doGetBean 完成
return doGetBean(name, null, null, false);
}
+
+deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
+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
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换名称:去除 FactoryBean 的前缀 &,将别名转换为规范名称
final String beanName = transformedBeanName(name);
Object bean;
// 检查单例缓存中是否已存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
// 如果已存在,直接返回该实例或者使用该实例(FactoryBean)创建并返回对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果当前 Bean 是一个正在创建中的 prototype 类型,表明可能发生循环引用
// 注意:Spring 并未解决 prototype 类型的循环引用问题,要抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果当前 beanFactory 没有 bean 定义,去 parent beanFactory 中查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 标记为至少创建过一次
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保 bean 依赖的 bean(构造器参数) 都已实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 注意:Spring 并未解决构造器方法中的循环引用问题,要抛异常
}
// 注册依赖关系,确保先销毁被依赖的 bean
registerDependentBean(dep, beanName);
// 递归,获取依赖的 bean
getBean(dep);
}
}
}
if (mbd.isSingleton()) {
// 如果是单例类型(绝大多数都是此类型)
// 再次从缓存中获取,如果仍不存在,则使用传入的 ObjectFactory 创建
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>(
{
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);
}
else if (mbd.isPrototype()) {
// 如果是原型类型,每次都新创建一个
// ...
}
else {
// 如果是其他 scope 类型
// ...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
+
+getSingleton
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 加锁
synchronized (this.singletonObjects) {
// 再次从缓存中获取(和调用前从缓存中获取构成双重校验)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
// 如果正在销毁单例,则抛异常
// 注意:不要在销毁方法中调用获取 bean 方法
}
// 创建前,先注册到正在创建中的集合
// 在出现循环引用时,第二次进入 doGetBean,用此作为判断标志
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// ...
try {
// 使用传入的单例工厂创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 如果异常的出现是因为 bean 被创建了,就忽略异常,否则抛出异常
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
// ...
}
finally {
// ...
// 创建后,从正在创建中集合移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加单例到缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
+
+创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// ...
try {
// 给 Bean 后置处理器一个返回代理的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...
// 常规的创建 Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
+
+doCreateBean
常规的创建 Bean 的具体工作是由 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
39
40
41
42
43
44
45
46
47
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 使用相应的策略创建 bean 实例,例如通过工厂方法或者有参、无参构造器方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// ...
// 使用 ObjectFactory 封装实例并缓存,以解决循环引用问题
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
// 填充属性(包括解析依赖的 bean)
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
// ...
// 如有需要,将 bean 注册为一次性的,以供 beanFactory 在关闭时调用销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// ...
return exposedObject;
}
+
+createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
+
+- 工厂方法
+- 构造器方法
+- 有参
+- 无参
+
+
+
+populateBean
为创建出的实例填充属性,包括解析当前 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
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// ...
// 给 InstantiationAwareBeanPostProcessors 一个机会,
// 在设置 bean 属性前修改 bean 状态,可用于自定义的字段注入
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 是否继续填充属性的流程
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否存在 InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 后置处理 PropertyValues
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 将属性应用到 bean 上(常规情况下,前面的处理都用不上)
applyPropertyValues(beanName, mbd, bw, pvs);
}
+
+initializeBean
在填充完属性后,实例就可以进行初始化工作:
+
+- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息
+- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
+- invokeInitMethods,调用初始化方法
+- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
+
+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
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 处理 Aware 接口的相应方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 应用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
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()) {
// 应用 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
+
+处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
+1
2
3
4
5
6
7
8
9
10
11
12
13
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
+
+调用初始化方法
+- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法
+- 如果自定义 init 方法且满足调用条件,同样进行调用
+
+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
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 是否实现 InitializingBean 接口,是的话调用 afterPropertiesSet 方法
// 给 bean 一个感知属性已设置并做出反应的机会
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean
&& (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 如果存在自定义的 init 方法且方法名称不是 afterPropertiesSet,判断是否调用
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null
&& !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
+
+BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
+
+- 获取 Processor 列表
+- 判断 Processor 类型是否是当前需要的
+- 对 bean 进行处理
+
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
+
+再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
+1
2
3
4
5
6
7
8
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
+
+在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
+
+- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。
+- Bean 自身的初始化。
+
+在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -1701,6 +1541,166 @@
-
+
@@ -1580,7 +1420,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Spring Bean 加载过程
+
+
+
+
+
+
+
+
+
+ Spring Bean 生命周期
+
+获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
+1
2
3
4
public Object getBean(String name) throws BeansException {
// 具体工作由 doGetBean 完成
return doGetBean(name, null, null, false);
}
+
+deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
+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
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换名称:去除 FactoryBean 的前缀 &,将别名转换为规范名称
final String beanName = transformedBeanName(name);
Object bean;
// 检查单例缓存中是否已存在
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
// 如果已存在,直接返回该实例或者使用该实例(FactoryBean)创建并返回对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 如果当前 Bean 是一个正在创建中的 prototype 类型,表明可能发生循环引用
// 注意:Spring 并未解决 prototype 类型的循环引用问题,要抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果当前 beanFactory 没有 bean 定义,去 parent beanFactory 中查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 标记为至少创建过一次
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 确保 bean 依赖的 bean(构造器参数) 都已实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
// 注意:Spring 并未解决构造器方法中的循环引用问题,要抛异常
}
// 注册依赖关系,确保先销毁被依赖的 bean
registerDependentBean(dep, beanName);
// 递归,获取依赖的 bean
getBean(dep);
}
}
}
if (mbd.isSingleton()) {
// 如果是单例类型(绝大多数都是此类型)
// 再次从缓存中获取,如果仍不存在,则使用传入的 ObjectFactory 创建
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>(
{
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);
}
else if (mbd.isPrototype()) {
// 如果是原型类型,每次都新创建一个
// ...
}
else {
// 如果是其他 scope 类型
// ...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
+
+getSingleton
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 加锁
synchronized (this.singletonObjects) {
// 再次从缓存中获取(和调用前从缓存中获取构成双重校验)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
// 如果正在销毁单例,则抛异常
// 注意:不要在销毁方法中调用获取 bean 方法
}
// 创建前,先注册到正在创建中的集合
// 在出现循环引用时,第二次进入 doGetBean,用此作为判断标志
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// ...
try {
// 使用传入的单例工厂创建对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 如果异常的出现是因为 bean 被创建了,就忽略异常,否则抛出异常
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
// ...
}
finally {
// ...
// 创建后,从正在创建中集合移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 添加单例到缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
+
+创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
// ...
try {
// 给 Bean 后置处理器一个返回代理的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// ...
// 常规的创建 Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
+
+doCreateBean
常规的创建 Bean 的具体工作是由 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
39
40
41
42
43
44
45
46
47
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 使用相应的策略创建 bean 实例,例如通过工厂方法或者有参、无参构造器方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// ...
// 使用 ObjectFactory 封装实例并缓存,以解决循环引用问题
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
// 填充属性(包括解析依赖的 bean)
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
// ...
// 如有需要,将 bean 注册为一次性的,以供 beanFactory 在关闭时调用销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
// ...
return exposedObject;
}
+
+createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
+
+- 工厂方法
+- 构造器方法
+- 有参
+- 无参
+
+
+
+populateBean
为创建出的实例填充属性,包括解析当前 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
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
// ...
// 给 InstantiationAwareBeanPostProcessors 一个机会,
// 在设置 bean 属性前修改 bean 状态,可用于自定义的字段注入
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 是否继续填充属性的流程
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
|| mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据名称注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否存在 InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要检查依赖
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 后置处理 PropertyValues
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 将属性应用到 bean 上(常规情况下,前面的处理都用不上)
applyPropertyValues(beanName, mbd, bw, pvs);
}
+
+initializeBean
在填充完属性后,实例就可以进行初始化工作:
+
+- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息
+- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
+- invokeInitMethods,调用初始化方法
+- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法
+
+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
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
// 处理 Aware 接口的相应方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 应用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
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()) {
// 应用 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
+
+处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
+1
2
3
4
5
6
7
8
9
10
11
12
13
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
+
+调用初始化方法
+- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法
+- 如果自定义 init 方法且满足调用条件,同样进行调用
+
+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
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
// 是否实现 InitializingBean 接口,是的话调用 afterPropertiesSet 方法
// 给 bean 一个感知属性已设置并做出反应的机会
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean
&& (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 如果存在自定义的 init 方法且方法名称不是 afterPropertiesSet,判断是否调用
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null
&& !(isInitializingBean && "afterPropertiesSet".equals(initMethodName))
&& !mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
+
+BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
+
+- 获取 Processor 列表
+- 判断 Processor 类型是否是当前需要的
+- 对 bean 进行处理
+
+1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
+
+再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
+1
2
3
4
5
6
7
8
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
+
+在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
+
+- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。
+- Bean 自身的初始化。
+
+在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
+
+
+
+
+
+
+
+
+
+
+
+ Spring Bean 加载过程 +
+ + +Spring Bean 生命周期
+ +获取 Bean
获取指定 Bean 的入口方法是 getBean,在 Spring 上下文刷新过程中,就依次调用 AbstractBeanFactory#getBean(java.lang.String)
方法获取 non-lazy-init
的 Bean。
1 | public Object getBean(String name) throws BeansException { |
deGetBean
作为公共处理逻辑,由 AbstractBeanFactory 自己实现。
+1 | protected <T> T doGetBean( |
getSingleton
1 | public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { |
创建 Bean
createBean 是创建 Bean 的入口方法,由 AbstractBeanFactory 定义,由 AbstractAutowireCapableBeanFactory 实现。
+1 | protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { |
doCreateBean
常规的创建 Bean 的具体工作是由 doCreateBean 完成的。
+1 | protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException { |
createBeanInstance
创建 Bean 实例,并使用 BeanWrapper 封装。实例化的方式:
+-
+
- 工厂方法 +
- 构造器方法
-
+
- 有参 +
- 无参 +
+
populateBean
为创建出的实例填充属性,包括解析当前 bean 所依赖的 bean。
+1 | protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { |
initializeBean
在填充完属性后,实例就可以进行初始化工作:
+-
+
- invokeAwareMethods,让 Bean 通过 xxxAware 接口感知一些信息 +
- 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法 +
- invokeInitMethods,调用初始化方法 +
- 调用 BeanPostProcessor 的 postProcessAfterInitialization 方法 +
1 | protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { |
处理 Aware 接口的相应方法
让 Bean 在初始化中,感知(获知)和自身相关的资源,如 beanName、beanClassLoader 或者 beanFactory。
+1 | private void invokeAwareMethods(final String beanName, final Object bean) { |
调用初始化方法
-
+
- 如果 bean 实现 InitializingBean 接口,调用 afterPropertiesSet 方法 +
- 如果自定义 init 方法且满足调用条件,同样进行调用 +
1 | protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { |
BeanPostProcessor 处理
在调用初始化方法前后,BeanPostProcessor 先后进行两次处理。其实和 BeanPostProcessor 相关的代码都非常相似:
+-
+
- 获取 Processor 列表 +
- 判断 Processor 类型是否是当前需要的 +
- 对 bean 进行处理 +
1 | public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { |
再思 Bean 的初始化
以下代码片段一度让我困惑,从注释看,初始化 Bean 实例的工作包括了 populateBean 和 initializeBean,但是 initializeBean 方法的含义就是初始化 Bean。在 initializeBean 方法中,调用了 invokeInitMethods 方法,其含义仍然是调用初始化方法。
在更熟悉代码后,我有一种微妙的、个人性的体会,在 Spring 源码中,有时候视角的变化是很快的,痕迹是很小的。如果不加以理解和区分,很容易迷失在相似的描述中。以此处为例,“初始化 Bean 和 Bean 的初始化”扩展开来是 “Bean 工厂初始化一个 Bean 和 Bean 自身进行初始化”。
1 | // Initialize the bean instance. |
在注释这一行,视角是属于 BeanFactory(AbstractAutowireCapableBeanFactory)。从工厂的视角,面对一个刚刚创建出来的 Bean 实例,需要完成两方面的工作:
+-
+
- 为 Bean 实例填充属性,包括解析依赖,为 Bean 自身的初始化做好准备。 +
- Bean 自身的初始化。 +
在万事俱备之后,就是 Bean 自身的初始化工作。由于 Spring 的高度扩展性,这部分并不只是单纯地调用初始化方法,还包含 Aware 接口和 BeanPostProcessor 的相关处理,前者偏属于 Java 对象层面,后者偏属于 Spring Bean 层面。
在认同 BeanPostProcessor 的处理属于 Bean 自身初始化工作的一部分后,@PostConstruct 注解的方法被称为 Bean 的初始化方法也就不那么违和了,因为它的实现原理正是 BeanPostProcessor,这仍然在 initializeBean 的范围内。
Moralok
-
+
diff --git a/leancloud_counter_security_urls.json b/leancloud_counter_security_urls.json
index 881386d7..3857eb32 100644
--- a/leancloud_counter_security_urls.json
+++ b/leancloud_counter_security_urls.json
@@ -1 +1 @@
-[{"title":"在 Ubuntu 上安装 Clash","url":"/2023/05/27/how-to-install-clash-on-ubuntu/"},{"title":"Docker 常用命令列表","url":"/2020/08/19/docker-frequently-used-commands/"},{"title":"在 iOS 和 macOS 上安装 OpenVPN 客户端","url":"/2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/"},{"title":"在 Windows 10 上安装 OpenVPN 服务器","url":"/2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/"},{"title":"使用 OpenVPN 访问家庭内网","url":"/2023/06/07/how-to-use-OpenVPN-to-access-home-network/"},{"title":"Ubuntu server 20.04 安装后没有分配全部磁盘空间","url":"/2023/06/24/Ubuntu-server-20-04-not-all-disk-space-was-allocated-after-installation/"},{"title":"如何使用 SSH 连接 Github 和服务器","url":"/2023/06/28/how-to-use-ssh-to-connect-github-and-server/"},{"title":"Tmux 常用命令和快捷键","url":"/2023/06/29/tmux-frequently-used-commands/"},{"title":"如何为终端、docker 和容器设置代理","url":"/2023/06/13/how-to-configure-proxy-for-terminal-docker-and-container/"},{"title":"如何在 Ubuntu 20.04 上安装 Minikube","url":"/2023/06/23/how-to-install-Minikube-on-Ubuntu-20-04/"},{"title":"JVM GC 的测试和分析","url":"/2023/11/01/testing-and-analysis-of-jvm-gc/"},{"title":"字符串常量池的测试和分析","url":"/2023/11/03/testing-and-analysis-of-StringTable/"},{"title":"Spring Bean 加载过程","url":"/2023/11/17/how-does-Spring-load-beans/"},{"title":"关于 Java 字节码指令的一些例子分析","url":"/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/"},{"title":"基于 Redis 的分布式锁的简单实现","url":"/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/"},{"title":"Java 类加载器源码分析","url":"/2023/07/13/Java-class-loader-source-code-analysis/"},{"title":"JVM 内存区域的测试和分析","url":"/2023/11/04/testing-and-analysis-of-jvm-memory-area/"},{"title":"Java 垃圾收集","url":"/2023/11/07/garbage-collection-in-Java/"}]
\ No newline at end of file
+[{"title":"在 Ubuntu 上安装 Clash","url":"/2023/05/27/how-to-install-clash-on-ubuntu/"},{"title":"在 iOS 和 macOS 上安装 OpenVPN 客户端","url":"/2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/"},{"title":"在 Windows 10 上安装 OpenVPN 服务器","url":"/2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/"},{"title":"使用 OpenVPN 访问家庭内网","url":"/2023/06/07/how-to-use-OpenVPN-to-access-home-network/"},{"title":"如何为终端、docker 和容器设置代理","url":"/2023/06/13/how-to-configure-proxy-for-terminal-docker-and-container/"},{"title":"Docker 常用命令列表","url":"/2020/08/19/docker-frequently-used-commands/"},{"title":"Ubuntu server 20.04 安装后没有分配全部磁盘空间","url":"/2023/06/24/Ubuntu-server-20-04-not-all-disk-space-was-allocated-after-installation/"},{"title":"Tmux 常用命令和快捷键","url":"/2023/06/29/tmux-frequently-used-commands/"},{"title":"如何使用 SSH 连接 Github 和服务器","url":"/2023/06/28/how-to-use-ssh-to-connect-github-and-server/"},{"title":"如何在 Ubuntu 20.04 上安装 Minikube","url":"/2023/06/23/how-to-install-Minikube-on-Ubuntu-20-04/"},{"title":"Spring Bean 加载过程","url":"/2023/08/10/how-does-Spring-load-beans/"},{"title":"JVM GC 的测试和分析","url":"/2023/11/01/testing-and-analysis-of-jvm-gc/"},{"title":"字符串常量池的测试和分析","url":"/2023/11/03/testing-and-analysis-of-StringTable/"},{"title":"Java 类加载器源码分析","url":"/2023/07/13/Java-class-loader-source-code-analysis/"},{"title":"关于 Java 字节码指令的一些例子分析","url":"/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/"},{"title":"基于 Redis 的分布式锁的简单实现","url":"/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/"},{"title":"JVM 内存区域的测试和分析","url":"/2023/11/04/testing-and-analysis-of-jvm-memory-area/"},{"title":"Java 垃圾收集","url":"/2023/11/07/garbage-collection-in-Java/"}]
\ No newline at end of file
diff --git a/page/2/index.html b/page/2/index.html
index 36d9d6ec..ab4a4a4e 100644
--- a/page/2/index.html
+++ b/page/2/index.html
@@ -158,7 +158,7 @@
-
+
@@ -2182,7 +2182,7 @@
-
+
@@ -2028,7 +2028,7 @@
Moralok
-
+
diff --git a/leancloud_counter_security_urls.json b/leancloud_counter_security_urls.json
index 881386d7..3857eb32 100644
--- a/leancloud_counter_security_urls.json
+++ b/leancloud_counter_security_urls.json
@@ -1 +1 @@
-[{"title":"在 Ubuntu 上安装 Clash","url":"/2023/05/27/how-to-install-clash-on-ubuntu/"},{"title":"Docker 常用命令列表","url":"/2020/08/19/docker-frequently-used-commands/"},{"title":"在 iOS 和 macOS 上安装 OpenVPN 客户端","url":"/2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/"},{"title":"在 Windows 10 上安装 OpenVPN 服务器","url":"/2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/"},{"title":"使用 OpenVPN 访问家庭内网","url":"/2023/06/07/how-to-use-OpenVPN-to-access-home-network/"},{"title":"Ubuntu server 20.04 安装后没有分配全部磁盘空间","url":"/2023/06/24/Ubuntu-server-20-04-not-all-disk-space-was-allocated-after-installation/"},{"title":"如何使用 SSH 连接 Github 和服务器","url":"/2023/06/28/how-to-use-ssh-to-connect-github-and-server/"},{"title":"Tmux 常用命令和快捷键","url":"/2023/06/29/tmux-frequently-used-commands/"},{"title":"如何为终端、docker 和容器设置代理","url":"/2023/06/13/how-to-configure-proxy-for-terminal-docker-and-container/"},{"title":"如何在 Ubuntu 20.04 上安装 Minikube","url":"/2023/06/23/how-to-install-Minikube-on-Ubuntu-20-04/"},{"title":"JVM GC 的测试和分析","url":"/2023/11/01/testing-and-analysis-of-jvm-gc/"},{"title":"字符串常量池的测试和分析","url":"/2023/11/03/testing-and-analysis-of-StringTable/"},{"title":"Spring Bean 加载过程","url":"/2023/11/17/how-does-Spring-load-beans/"},{"title":"关于 Java 字节码指令的一些例子分析","url":"/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/"},{"title":"基于 Redis 的分布式锁的简单实现","url":"/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/"},{"title":"Java 类加载器源码分析","url":"/2023/07/13/Java-class-loader-source-code-analysis/"},{"title":"JVM 内存区域的测试和分析","url":"/2023/11/04/testing-and-analysis-of-jvm-memory-area/"},{"title":"Java 垃圾收集","url":"/2023/11/07/garbage-collection-in-Java/"}]
\ No newline at end of file
+[{"title":"在 Ubuntu 上安装 Clash","url":"/2023/05/27/how-to-install-clash-on-ubuntu/"},{"title":"在 iOS 和 macOS 上安装 OpenVPN 客户端","url":"/2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/"},{"title":"在 Windows 10 上安装 OpenVPN 服务器","url":"/2023/06/07/how-to-setup-OpenVPN-server-on-windows-10/"},{"title":"使用 OpenVPN 访问家庭内网","url":"/2023/06/07/how-to-use-OpenVPN-to-access-home-network/"},{"title":"如何为终端、docker 和容器设置代理","url":"/2023/06/13/how-to-configure-proxy-for-terminal-docker-and-container/"},{"title":"Docker 常用命令列表","url":"/2020/08/19/docker-frequently-used-commands/"},{"title":"Ubuntu server 20.04 安装后没有分配全部磁盘空间","url":"/2023/06/24/Ubuntu-server-20-04-not-all-disk-space-was-allocated-after-installation/"},{"title":"Tmux 常用命令和快捷键","url":"/2023/06/29/tmux-frequently-used-commands/"},{"title":"如何使用 SSH 连接 Github 和服务器","url":"/2023/06/28/how-to-use-ssh-to-connect-github-and-server/"},{"title":"如何在 Ubuntu 20.04 上安装 Minikube","url":"/2023/06/23/how-to-install-Minikube-on-Ubuntu-20-04/"},{"title":"Spring Bean 加载过程","url":"/2023/08/10/how-does-Spring-load-beans/"},{"title":"JVM GC 的测试和分析","url":"/2023/11/01/testing-and-analysis-of-jvm-gc/"},{"title":"字符串常量池的测试和分析","url":"/2023/11/03/testing-and-analysis-of-StringTable/"},{"title":"Java 类加载器源码分析","url":"/2023/07/13/Java-class-loader-source-code-analysis/"},{"title":"关于 Java 字节码指令的一些例子分析","url":"/2023/11/09/some-examples-of-Java-bytecode-instruction-analysis/"},{"title":"基于 Redis 的分布式锁的简单实现","url":"/2023/11/13/simple-implementation-of-distributed-lock-based-on-Redis/"},{"title":"JVM 内存区域的测试和分析","url":"/2023/11/04/testing-and-analysis-of-jvm-memory-area/"},{"title":"Java 垃圾收集","url":"/2023/11/07/garbage-collection-in-Java/"}]
\ No newline at end of file
diff --git a/page/2/index.html b/page/2/index.html
index 36d9d6ec..ab4a4a4e 100644
--- a/page/2/index.html
+++ b/page/2/index.html
@@ -158,7 +158,7 @@
proxy
+
+ 在 iOS 和 macOS 上安装 OpenVPN 客户端
+ /2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/
+ 安装 OpenVPN Connect
-
+
diff --git a/search.xml b/search.xml
index caf717a6..7947b806 100644
--- a/search.xml
+++ b/search.xml
@@ -45,6 +45,176 @@
-
+
@@ -1151,7 +1151,7 @@
-
+
@@ -1018,7 +1018,7 @@
-
+
@@ -897,7 +897,7 @@
-
+
@@ -781,7 +781,7 @@
-
+
@@ -633,7 +633,7 @@
-
+
@@ -493,7 +493,7 @@
-
+
@@ -343,7 +343,7 @@
proxy
+
+ 在 iOS 和 macOS 上安装 OpenVPN 客户端
+ /2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/
+ 安装 OpenVPN Connect
-
+
diff --git a/search.xml b/search.xml
index caf717a6..7947b806 100644
--- a/search.xml
+++ b/search.xml
@@ -45,6 +45,176 @@
-
+
@@ -1151,7 +1151,7 @@
-
+
@@ -1018,7 +1018,7 @@
-
+
@@ -897,7 +897,7 @@
-
+
@@ -781,7 +781,7 @@
-
+
@@ -633,7 +633,7 @@
proxy
+
+ 在 iOS 和 macOS 上安装 OpenVPN 客户端
+ /2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/
+ 安装 OpenVPN Connect
-
+
diff --git a/search.xml b/search.xml
index caf717a6..7947b806 100644
--- a/search.xml
+++ b/search.xml
@@ -45,6 +45,176 @@
-
+
@@ -1151,7 +1151,7 @@
-
+
@@ -1018,7 +1018,7 @@
-
+
@@ -897,7 +897,7 @@
proxy
+
+ 在 iOS 和 macOS 上安装 OpenVPN 客户端
+ /2023/06/07/how-to-setup-OpenVPN-connect-client-on-iOS-and-macOS/
+ 安装 OpenVPN Connect
-
+
diff --git a/search.xml b/search.xml
index caf717a6..7947b806 100644
--- a/search.xml
+++ b/search.xml
@@ -45,6 +45,176 @@
-
+
@@ -1151,7 +1151,7 @@ macOS 访问官网下载。
iOS 访问 AppStore,需要登录外区 Apple ID。
配置 OpenVPN Connect
客户端提供了两种方式导入配置文件,一是通过 URL,建议 URL 仅限在私有网络内访问,二是通过其他方式例如邮件,下载为本地文件再导入。
+配置文件的组织方式又分为两种形式,一种是将 CA 根证书 ca.crt,客户端证书 client.crt,客户端密钥 client.key 的内容复制粘贴到 client.ovpn 中,形成一个联合配置文件;另一种是使用 openssl 将 CA 根证书 ca.crt,客户端证书 client.crt,客户端密钥 client.key 转换为 PKCS#12 文件,先后导入 client.ovpn12 和 client.ovpn。
+单一 client.ovpn
从目录 C:\Program Files\OpenVPN\sample-config
复制客户端配置文件模板 client.ovpn,修改以下配置:
remote your-server 1194 |
将 remote your-server 1194
中的地址和端口替换成你的 OpenVPN server 的地址和端口。将 ca ca.crt
, cert client.crt
, key client.key
, tls-auth ta.key 1
注释掉,将各自文件中的内容以上述类 XML 的形式粘贴到 client.ovpn 中。
将修改好的客户端配置文件导入到客户端中即可。
+client.ovpn + client.opvn12
使用 openssl 命令将客户端的证书和私钥文件转换为 PKCS#12 形式的文件。该命令会提示 Enter Export Password
,可以为空,但为了安全建议设置密码。
openssl pkcs12 -export -in cert -inkey key -certfile ca -name MyClient -out client.ovpn12 |
由于在 iOS 中导入 PKCS#12 文件到 Keychain 中时只导入了客户端证书和密钥,CA 根证书并没有导入,client.ovpn 文件中必须要保留 CA 根证书的配置。
既可以用传统的引用文件的方式:
ca ca.crt |
也可以用类 XML 的形式粘贴 ca.crt 内容到 client.ovpn 中:
+<ca> |
先导入 client.ovpn12(需要输入转换时的密码),再导入 client.ovpn。
+++但是我失败了……导入 client.ovpn12 时密码一直错误,搜索到类似的案例,但是没有找到解决方案。不确定是不是 openssl 版本引起的。
+
路由器 NAT
在路由器管理后台的 NAT 设置功能里,配置好对外端口号和 Windows 10 主机上 OpenVPN 端口号的映射关系。
+参考链接
iOS 使用 OpenVPN 的 FAQ
如何通过 iOS Keychain 使用客户端证书和密钥
如何配置 iOS OpenVPN 客户端的证书认证
从 OpenVPN 社区 下载 Windows 64-bit MSI installer。本次安装的版本为 OpenVPN 2.6.4。
+++注意事项:在选择安装类型时选择 Customize 而不要选择 Install Now。额外勾选 OpenVPN -> OpenVPN Service -> Entire feature will be installed on local hard drive 和 OpenSSL Utilities -> EasyRSA 3 Certificate Management Scripts -> Entire feature will be installed on local hard drive。
+
安装完毕后,会弹出一条消息提示未找到可读的连接配置文件,暂时忽略。
此时在 控制面板\网络和 Internet\网络连接 中可以看到创建了两个新的网络适配器 OpenVPN TAP-Windows6 和 OpenVPN Wintun。
配置 OpenVPN server
打开 Windows 10 终端程序。
进入 OpenVPN 默认安装目录中的 easy-rsa 目录。
cd 'C:\Program Files\OpenVPN\easy-rsa' |
执行命令进入 Easy-RSA 3 Shell
+.\EasyRSA-Start.bat |
初始化公钥基础设施目录 pki
+./easyrsa init-pki |
构建证书颁发机构(CA)密钥,CA 根证书文件将在后续用于对其他证书和密钥进行签名。该命令要求输入 Common Name,输入主机名即可。创建的 ca.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki
中,ca.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
./easyrsa build-ca nopass |
构建服务器证书和密钥。创建的 server.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\issued
中,server.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
./easyrsa build-server-full server nopass |
构建客户端证书和密钥。创建的 client.crt 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\issued
中,client.key 保存在目录 C:\Program Files\OpenVPN\easy-rsa\pki\private
中。
./easyrsa build-client-full client nopass |
生成 Diffie-Hellman 参数
+./easyrsa gen-dh |
从目录 C:\Program Files\OpenVPN\sample-config
复制服务端配置文件模板 server.ovpn 到目录 C:\Program Files\OpenVPN\config
中,修改以下配置:
port 1194 |
端口号按需修改,默认为1194,需要保证 OpenVPN 的网络流量可以通过防火墙,设置 Windows 10 Defender 允许 OpenVPN 通过即可。dh2048.pem 修改为生成的文件名 dh.pem。取消注释 duplicate-cn,让多个客户端使用同一个客户端证书。注释掉 tls-auth ta.key 0。复制 ca.crt,dh.pem,server.crt 和 server.key 到目录 C:\Program Files\OpenVPN\config 中。
+启动与连接
启动 OpenVPN,点击连接,系统提示分配 IP 10.8.0.1。按配置,每次 OpenVPN server 都将为自己分配 10.8.0.1。
+参考链接
openvpn安装配置说明(windows系统)
如何在Windows 10上安装和配置OpenVPN
宽带是电信宽带,分配了动态的公网 IP。
光猫使用桥接模式,通过路由器拨号上网(PPPoE),路由器局域网为 192.168.3.0/24。
一台 Windows 10 主机,在路由器局域网上的 IP 192.168.3.120。。
Windows 10 主机上运行 Vmware 虚拟机,网络采用 NAT 模式。子网为 192.168.46.0/24。运行了 Linux 主机,IP 192.168.46.128。Windows 10 主机在子网中的 IP 为 192.168.3.1。
子网 | +Windows 10 主机 | +Linux 主机 | +客户端 | +
---|---|---|---|
路由器 192.168.3.0/24 | +192.168.3.120 | +- | +- | +
Vmware NAT 192.168.46.0/24 | +192.168.46.1 | +192.168.46.128 | +- | +
VPN 10.8.0.0/24 | +10.8.0.1 | +- | +10.8.0.6 | +
目标和考虑因素
-
+
- 能从公网访问家庭内网,包括 Windows 10 主机和虚拟机上的 Linux 主机。 +
- 不想通过路由器的 NAT 功能直接将路由器局域网上的设备映射到公网。一是为了安全,二是为了避免运营商审查。 +
- 已经尝试过使用 ZeroTier,将所需设备组建在一个局域网当中,可以作为备选方案。同时不想每次新增设备都安装 ZeroTier。 +
- 想利用公网 IP 以及上行带宽尝尝鲜。 +
- 想要能直连虚拟机上的 Linux 主机,而不是通过 Vmware 的 NAT 映射。不想每次新增服务都要设置 NAT,修改 Windows Defender 的规则。 +
实现过程
在 Windows 10 上安装 OpenVPN 服务器
见在 Windows 10 上安装 OpenVPN 服务器。
+在 iOS 和 macOS 上安装 OpenVPN 客户端
见在 iOS 和 macOS 上安装 OpenVPN 客户端。
+客户端访问服务端其他的私有子网
如果在所需的每一个设备上都安装 OpenVPN,将它们连接在 VPN 的子网 10.8.0.0/24 中,也是可以满足需求的,但是这和每个设备都安装 ZeroTier 差不多。
+server.ovpn 新增配置
在 server.ovpn
配置文件中新增一行配置,这个配置的意思是将该路由配置统一推送给客户端,让它们可以访问服务端的其他私有子网。相当于将服务端的其他私有子网的情况告知客户端,这样客户端就知道发往 192.168.46.128 的 Packet 是发向哪里的。
push "route 192.168.46.0 255.255.255.0" |
打开 Windows 10 主机的路由转发功能
-
+
Win + R
输入 regedit 打开注册表。
+- 找到
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
,修改IPEnableRouter
为 1。
+ - 重启 +
为虚拟机上的 Linux 主机新增路由
在终端中输入命令:
+route add -net 10.8.0.0/24 gw 192.168.46.1 |
这是为了让 OpenVPN 服务端的其他私有子网上的设备知道来自 10.8.0.0/24 的 IP Packet 应该路由回 OpenVPN 服务端。
+参考链接
透过openvpn来访问内网资源
OpenVPN 路由详解
OpenVPN中的另一个路由问题 - 在VPN上无法访问本地计算机
openvpn添加本地路由表
windows开启路由转发
linux route命令的使用详解
Windows命令行route命令使用图解
为终端设置代理
有时候,我们需要在终端通过执行命令的方式访问网络和下载资源,比如使用 wget
和 curl
。
设置 Shell 环境变量
这一类软件都是可以通过为 Shell 设置环境变量的方式来设置代理,涉及到的环境变量有 http_proxy
、https_proxy
和 no_proxy
。
仅为当前会话设置,执行命令:
export http_proxy=http://proxyAddress:port |
永久设置代理,在设置 Shell 环境变量的脚本中(不同 Shell 的配置文件不同,比如 ~/.bashrc
或 ~/.zshrc
)添加:
export http_proxy=http://proxyAddress:port |
重新启动一个会话或者执行命令 source ~/.bashrc
使其在当前会话立即生效。
修改 wget 配置文件
在搜索过程中发现还可以在 wget
的配置文件 ~/.wgetrc
中添加:
use_proxy = on |
为 docker 设置代理
如果你以为为终端设置代理后 docker 就会使用代理,那你就错了。在从官方的镜像仓库 pull 镜像反复出错后并收到类似 Error response from daemon: Get "https://registry-1.docker.io/v2/": read tcp 192.168.3.140:59460->44.205.64.79:443: read: connection reset by peer
这样的报错信息后,我才开始怀疑我并没有真正给 docker 设置好代理。
在执行 docker pull
命令时,实际上命令是由守护进程 docker daemon
执行的。
通过 systemd 设置
如果你的 docker daemon
是通过 systemd
管理的,那么你可以通过设置 docker.service
服务的环境变量来设置代理。
执行命令查看 docker.service
信息,得知配置文件位置 /lib/systemd/system/docker.service
。
systemctl status docker.service |
在 docker.service
的 [Service]
模块添加:
Environment=HTTP_PROXY=http://proxyAddress:port |
重新加载配置文件并重启服务:
+systemctl daemon-reload |
修改 dockerd 配置文件
还可以修改 dockerd
配置文件,添加:
export http_proxy="http://proxyAddress:port" |
然后重启 docker daemon
即可。
++国内的镜像仓库在绝大多数时候都可以满足条件,但是存在个别镜像同步不及时的情况,如果使用 latest 标签拉取到的镜像并非近期的镜像,因此有时候需要直接从官方镜像仓库拉取镜像。
+
为 docker 容器设置代理
为 docker daemon
进程设置代理和为 docker 容器设置代理是有区别的。比如使用 docker 启动媒体服务器 jellyfin 后,jellyfin 的刮削功能就需要代理才能正常使用,这时候不要因为在很多地方设置过代理就以为容器内部已经在使用代理了。
修改配置文件
创建或修改 ~/.docker/config.json
,添加:
{ |
此后创建的新容器,会自动设置环境变量来使用代理。
+为指定容器添加环境变量
在启动容器时使用 -e
手动注入环境变量 http_proxy
。这意味着进入容器使用 export
设置环境变量的方式也是可行的。
++注意:如果代理是使用宿主机的代理,当网络为
+bridge
模式,proxyAddress 需要填写宿主机的 IP;如果使用host
模式,proxyAddress 可以填写 127.0.0.1。
总结
不要因为在很多地方设置过代理,就想当然地以为当前的访问也是经过代理的。每个软件设置代理的方式不尽相同,但是大体上可以归结为:
+-
+
- 使用系统的环境变量 +
- 修改软件的配置文件 +
- 执行时注入参数 +
举一反三,像 apt
和 git
这类软件也是有其设置代理的方法。当你的代理稳定但是相应的访问失败时,大胆假设你的代理没有设置成功。要理清楚,当前的访问是谁发起的,才能正确地使用关键词搜索到正确的设置方式。
++原本我在 docker 相关的使用中,有关代理的设置方式是通过修改配置文件,实现永久、全局的代理配置。但是在后续的使用中,发现代理在一些场景(比如使用 cloudflare tunnel)中会引起不易排查的问题,决定采用临时、局部的配置方式。
+
参考链接
Linux 让终端走代理的几种方法
Linux ❀ wget设置代理
配置Docker使用代理
Docker的三种网络代理配置
docker 设置代理,以及国内加速镜像设置