Skip to content

Commit 224c8b2

Browse files
author
yangjingjing
committed
init blog
1 parent 98ecae4 commit 224c8b2

File tree

49 files changed

+8498
-1047
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+8498
-1047
lines changed

_posts/2015-02-03-Object类.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
layout: post
3-
categories: JDK
3+
categories: [JDK]
44
description: none
55
keywords: JDK
66
---

_posts/2019-01-17-Spring容器实现.md

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ XML配置文件的读取是Spring中重要的功能,因为Spring的大部分
107107
通过实现接口BeanDefinitionDocumentReader的DefaultBeanDefinitionDocumentReader类对Document进行解析,并使用BeanDefinitionParserDelegate对Element进行解析。
108108

109109
## 容器的基础XmlBeanFactory
110-
```java
110+
```
111111
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanFactoryTest.xml"));
112112
```
113113
时序图从BeanFactoryTest测试类开始,通过时序图我们可以一目了然地看到整个逻辑处理顺序。在测试的BeanFactoryTest中首先调用ClassPathResource的构造函数来构造Resource资源文件的实例对象,这样后续的资源处理就可以用Resource提供的各种服务来操作了,当我们有了Resource后就可以进行XmlBeanFactory的初始化了。那么Resource资源是如何封装的呢?
@@ -140,7 +140,7 @@ Resource接口抽象了所有Spring内部使用到的底层资源:File、URL
140140
对不同来源的资源文件都有相应的Resource实现:文件(FileSystemResource)、Classpath资源(ClassPathResource)、URL资源(UrlResource)、InputStream资源(InputStreamResource)、Byte数组(ByteArrayResource)等。
141141

142142
在日常的开发工作中,资源文件的加载也是经常用到的,可以直接使用Spring提供的类,比如在希望加载文件时可以使用以下代码:
143-
```java
143+
```
144144
Resource resource=new ClassPathResource("beanFactoryTest.xml");
145145
InputStream inputStream=resource.getInputStream();
146146
```
@@ -149,15 +149,15 @@ InputStream inputStream=resource.getInputStream();
149149
有了Resource接口便可以对所有资源文件进行统一处理。至于实现,其实是非常简单的,以getInputStream为例,ClassPathResource中的实现方式便是通过class或者classLoader提供的底层方法进行调用,而对于FileSystemResource的实现其实更简单,直接使用FileInputStream对文件进行实例化。
150150

151151
ClassPathResource.java
152-
```java
152+
```
153153
if (this.clazz != null) {
154154
is = this.clazz.getResourceAsStream(this.path);
155155
}else {
156156
is = this.classLoader.getResourceAsStream(this.path);
157157
}
158158
```
159159
FileSystemResource.java
160-
```java
160+
```
161161
public InputStream getInputStream() throws IOException {
162162
return new FileInputStream(this.file);
163163
}
@@ -166,14 +166,14 @@ public InputStream getInputStream() throws IOException {
166166

167167
了解了Spring中将配置文件封装为Resource类型的实例方法后,我们就可以继续探寻XmlBeanFactory的初始化过程了,XmlBeanFactory的初始化有若干办法,Spring中提供了很多的构造函数,在这里分析的是使用Resource实例作为构造函数参数的办法,代码如下:
168168
XmlBeanFactory.java
169-
```java
169+
```
170170
public XmlBeanFactory(Resource resource) throws BeansException {
171171
//调用XmlBeanFactory(Resource,BeanFactory)构造方法
172172
this(resource, null);
173173
}
174174
```
175175
构造函数内部再次调用内部构造函数:
176-
```java
176+
```
177177
//parentBeanFactory为父类BeanFactory用于factory合并,可以为空
178178
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws
179179
BeansException {
@@ -182,7 +182,7 @@ BeansException {
182182
}
183183
```
184184
上面函数中的代码this.reader.loadBeanDefinitions(resource) 才是资源加载的真正实现,也是我们分析的重点之一。我们可以看到时序图中提到的XmlBeanDefinitionReader加载数据就是在这里完成的,但是在XmlBeanDefinitionReader加载数据前还有一个调用父类构造函数初始化的过程:super(parentBeanFactory),跟踪代码到父类AbstractAutowireCapableBeanFactory的构造函数中:
185-
```java
185+
```
186186
public AbstractAutowireCapableBeanFactory() {
187187
super();
188188
ignoreDependencyInterface(BeanNameAware.class);
@@ -253,7 +253,14 @@ public void refresh() throws BeansException, IllegalStateException {
253253
}
254254
```
255255

256+
## Bean创建
257+
个人认为在 Spring 中Bean的 创建时可以分为两个阶段:
258+
259+
Bean对应的BeanDefinition 的创建。BeanDefinition 创建是在 ConfigurationClassPostProcessor 中完成
260+
261+
Bean 实例的创建。Bean实例的创建是在 AbstractApplicationContext#finishBeanFactoryInitialization 中完成
256262

263+
之所以需要创建BeanDefinition 是因为在 Spring容器中,Bean的创建并非仅仅通过反射创建就结束了,在创建过程中,需要考虑到Bean针对Spring容器中的一些属性,所以BeanDefinition 中不仅仅包含了 Bean Class 文件信息,还包含了 当前Bean在Spring容器中的一些属性,比如在容器中的作用域、是否懒加载、别名等信息。当Bean 进行实例化创建时需要依赖于对应的BeanDefinition 提供对应的信息。
257264

258265

259266

0 commit comments

Comments
 (0)