SHAN


  • Home

  • Archives

【Elasticsearch】GET流程

Posted on 2019-01-31

GET基本流程

GET是根据index、type和ID向ES发送请求,获取文档数据,是读取操作,因此主分片或者副本分片都可以返回文档,不过新增的文档已经写入到主分片中但是还没有复制到副本分片时,副本分片可能会报告文档不存在。

假设有三个节点,分别存储着分片0和分片1,P开头的为主分片,R开头的为副本分片:

1.客户端向节点1发送GET请求

2.节点根据文档的ID判断文档属于哪个分片,这里假设文档属于分片0,通过集群状态中的内容路由表得知三个节点Node1、Node2、Node3中都含有分片0,此时节点1可以将请求发送给任意节点,假设发给了节点2

3.节点2根据ID从分片0上获取文档,然后将文档返回给节点1,由节点1返回给客户端

源码分析

协调节点

1.路由
  • 首先获取集群状态、节点列表等信息
  • 根据路由算法(或者是请求参数中指定的优先级和集群状态确定)获取文档所在的分片,因为分片可能存在副本,因此得到的是一个列表

TransportSingleShardAction

TransportSingleShardAction.AsyncSingleAction的构造函数中,准备集群状态、节点列表等信息,并计算文档所在分片:

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
public abstract class TransportSingleShardAction<Request extends SingleShardRequest<Request>, Response extends ActionResponse> extends TransportAction<Request, Response> {

class AsyncSingleAction {

private final ActionListener<Response> listener;
private final ShardsIterator shardIt;
private final InternalRequest internalRequest;
private final DiscoveryNodes nodes;
private volatile Exception lastFailure;

private AsyncSingleAction(Request request, ActionListener<Response> listener) {
this.listener = listener;
// 集群状态
ClusterState clusterState = clusterService.state();
if (logger.isTraceEnabled()) {
logger.trace("executing [{}] based on cluster state version [{}]", request, clusterState.version());
}
// 集群中的节点列表
nodes = clusterState.nodes();
ClusterBlockException blockException = checkGlobalBlock(clusterState);
if (blockException != null) {
throw blockException;
}

String concreteSingleIndex;
if (resolveIndex(request)) {
// 获取索引名称
concreteSingleIndex = indexNameExpressionResolver.concreteSingleIndex(clusterState, request).getName();
} else {
concreteSingleIndex = request.index();
}
// 创建InternalRequest对象
this.internalRequest = new InternalRequest(request, concreteSingleIndex);
// 解析请求
resolveRequest(clusterState, internalRequest);
blockException = checkRequestBlock(clusterState, internalRequest);
if (blockException != null) {
throw blockException;
}
// 根据路由算法得到文档属于哪个shard,或者根据请求中设置的参数选择,因为分片可能存在多个副本,因此得到的是一个迭代器
this.shardIt = shards(clusterState, internalRequest);
}
}

}

2.转发
  • 根据分片所在的节点ID从集群中的节点列表获取该节点,得到目标节点
  • 调用TransportService的sendRequest方法向目标节点转发请求,在转发之前判断本机节点是否是目标节点:

    (1)如果本机节点是目标节点,返回的连接是localNodeConnection,进入TransportService的sendLocalRequest流程

    (2)如果本机节点不是目标节点,返回一个连接目标节点的Connection,然后异步发送请求到网络,等待处理的Response

  • 等待数据节点的回复,如果数据节点处理成功,返回给客户端,如果处理失败进行重试

TransportSingleShardAction

TransportSingleShardAction.AsyncSingleAction的perform方法向目标节点转发请求:

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
private void perform(@Nullable final Exception currentFailure) {

......

final ShardRouting shardRouting = shardIt.nextOrNull();
......

// 根据分片所在的节点ID从集群中的节点列表获取该节点,得到目标节点
DiscoveryNode node = nodes.get(shardRouting.currentNodeId());
// 如果节点为空抛出异常
if (node == null) {
onFailure(shardRouting, new NoShardAvailableActionException(shardRouting.shardId()));
} else {
// 目标分片的id
internalRequest.request().internalShardId = shardRouting.shardId();
if (logger.isTraceEnabled()) {
logger.trace(
"sending request [{}] to shard [{}] on node [{}]",
internalRequest.request(),
internalRequest.request().internalShardId,
node
);
}
// 向目标节点转发请求
transportService.sendRequest(node, transportShardAction, internalRequest.request(), new TransportResponseHandler<Response>() {

@Override
public Response newInstance() {
return newResponse();
}

@Override
public String executor() {
return ThreadPool.Names.SAME;
}

@Override
public void handleResponse(final Response response) {
listener.onResponse(response);
}

@Override
public void handleException(TransportException exp) {
onFailure(shardRouting, exp);
}
});
}
}

TransportService

TransportService实现了sendRequest方法,在转发请求前,调用getConnection判断当前节点是否是目标节点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class TransportService extends AbstractLifecycleComponent {
public <T extends TransportResponse> void sendRequest(final DiscoveryNode node, final String action,
final TransportRequest request,
final TransportResponseHandler<T> handler) {
try {
// 获取目标节点的连接
Transport.Connection connection = getConnection(node);
// 向目标节点发送请求
sendRequest(connection, action, request, TransportRequestOptions.EMPTY, handler);
} catch (NodeNotConnectedException ex) {
// the caller might not handle this so we invoke the handler
handler.handleException(ex);
}
}

public Transport.Connection getConnection(DiscoveryNode node) {
// 判断当前节点是否是目标节点
if (isLocalNode(node)) {
return localNodeConnection;
} else {
// 如果当前节点不是目标节点,获取目标节点的连接
return transport.getConnection(node);
}
}
}

数据节点

数据节点收到协调节点的请求,读取数据并返回Response,入口在TransportSingleShardAction.ShardTransportHandler的messageReceived方法中。

TransportSingleShardAction

TransportSingleShardAction.ShardTransportHandler的messageReceived是接收协调节点请求的入口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public abstract class TransportSingleShardAction<Request extends SingleShardRequest<Request>, Response extends ActionResponse> extends TransportAction<Request, Response> {

private class ShardTransportHandler implements TransportRequestHandler<Request> {

@Override
public void messageReceived(final Request request, final TransportChannel channel) throws Exception {
if (logger.isTraceEnabled()) {
logger.trace("executing [{}] on shard [{}]", request, request.internalShardId);
}
// 读取数据并封装成Response
Response response = shardOperation(request, request.internalShardId);
// 发送响应
channel.sendResponse(response);
}
}
}

具体的读取过程:

TransportGetAction

TransportGetAction的shardOperation方法中调用了ShardGetService的get方法读取数据并存入GetResult中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class TransportGetAction extends TransportSingleShardAction<GetRequest, GetResponse> {

@Override
protected GetResponse shardOperation(GetRequest request, ShardId shardId) {
IndexService indexService = indicesService.indexServiceSafe(shardId.getIndex());
IndexShard indexShard = indexService.getShard(shardId.id());
// 检查是否需要refresh
if (request.refresh() && !request.realtime()) {
indexShard.refresh("refresh_flag_get");
}
// 调用ShardGetService的get方法读取数据并存入GetResult中
GetResult result = indexShard.getService().get(request.type(), request.id(), request.storedFields(),
request.realtime(), request.version(), request.versionType(), request.fetchSourceContext());
return new GetResponse(result);
}
}

ShardGetService

ShardGetService的get中又调用了innerGet方法,这里才是核心的数据读取实现:

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
public final class ShardGetService extends AbstractIndexShardComponent {
private GetResult innerGet(String type, String id, String[] gFields, boolean realtime, long version, VersionType versionType, FetchSourceContext fetchSourceContext) {
fetchSourceContext = normalizeFetchSourceContent(fetchSourceContext, gFields);
final Collection<String> types;
// 处理_all选项
if (type == null || type.equals("_all")) {
types = mapperService.types();
} else {
types = Collections.singleton(type);
}

Engine.GetResult get = null;
for (String typeX : types) {
Term uidTerm = mapperService.createUidTerm(typeX, id);
if (uidTerm != null) {
// 调用indexShard.get获取读取数据,
get = indexShard.get(new Engine.Get(realtime, typeX, id, uidTerm)
.version(version).versionType(versionType));
if (get.exists()) {
type = typeX;
break;
} else {
get.release();
}
}
}

if (get == null || get.exists() == false) {
// 返回结果
return new GetResult(shardId.getIndexName(), type, id, -1, false, null, null);
}

try {
// 对读取的数据进行过滤
return innerGetLoadFromStoredFields(type, id, gFields, fetchSourceContext, get, mapperService);
} finally {
get.release();
}
}
}

indexShard.get()方法返回的Engine.GetResult类型,在get方法中又调用了InternalEngine的get方法读取数据

IndexShard

1
2
3
4
5
6
public class IndexShard extends AbstractIndexShardComponent implements IndicesClusterStateService.Shard {
public Engine.GetResult get(Engine.Get get) {
readAllowed();
return getEngine().get(get, this::acquireSearcher);
}
}

InternalEngine

InternalEngine的get方法读取数据,在早期的ES版本中,刚写入的数据可以从translog读取,以此达到实时搜索,所以读取过程中会加锁,处理realtime选项,如果realtime为true,判断是否需要刷盘。ES 5之后不再从translog中读取,只从Lucene中读取,实时搜索依靠refresh实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class InternalEngine extends Engine {
@Override
public GetResult get(Get get, BiFunction<String, SearcherScope, Searcher> searcherFactory) throws EngineException {
assert Objects.equals(get.uid().field(), uidField) : get.uid().field();
// 加锁
try (ReleasableLock ignored = readLock.acquire()) {
ensureOpen();
SearcherScope scope;
// 处理realtime选项。判断是否需要刷盘
if (get.realtime()) {
VersionValue versionValue = versionMap.getUnderLock(get.uid().bytes());
if (versionValue != null) {
if (versionValue.isDelete()) {
return GetResult.NOT_EXISTS;
}
if (get.versionType().isVersionConflictForReads(versionValue.version, get.version())) {
throw new VersionConflictEngineException(shardId, get.type(), get.id(),
get.versionType().explainConflictForReads(versionValue.version, get.version()));
}
// 执行刷盘操作
refresh("realtime_get", SearcherScope.INTERNAL);
}
scope = SearcherScope.INTERNAL;
} else {

scope = SearcherScope.EXTERNAL;
}

// 调用searcher读取数据
return getFromSearcher(get, searcherFactory, scope);
}
}
}

数据节点读取流程总结:

  • 数据节点接收到协调节点的请求读取数据
  • 读取数据的核心实现是在ShardGetService的innerGet方法中实现的,在这个过程中,又依靠InternalEngine的get方法通过Searcher从Lucene中读取数据,然后innerGetLoadFromStoredFields方法对得到的数据进行过滤
  • 数据节点将返回结果封装到Response中返回

参考:

Elasticsearch源码解析与优化实战【张超】

Elasticsearch版本:6.1.2

【Elasticsearch】写入流程

Posted on 2019-01-30

Elasticsearch写入分为单个文档的写入和批量写入,单个文档的写入称作Index请求,批量写入称为Bulk请求,他们具有相同的处理逻辑,请求被统一封装为BuklRequest。

单个文档的写入流程:

1.客户端向Node1发送写入请求

2.Node1使用文档的id确定文档属于分片0,因为分片0的主分片不在当前节点,此时Node1充当协调节点,通过集群状态中的路由表可知分片0的主分片位于Node3,请求将会被转发到Node3

3.Node3上的主分片执行写入操作(需要有足够的活跃分片数),如果写入成功,将请求转发到Node1和Node2上,因为这两个节点都有分片0的副本分片,Node3等待所有副本分片的响应结果,当所有的分片都写入成功时,Node3向协调节点发送响应,再由协调节点Node1向客户端报告写入成功

1.活跃的分片数

1
2
3
4
public final Request waitForActiveShards(ActiveShardCount waitForActiveShards) {
this.waitForActiveShards = waitForActiveShards;
return (Request) this;
}

ES写入一致性的默认策略是quorum,即多数的分片在写入操作时处于可用状态,计算方式如下:
quorum = int((primary + number_of_replicas)/ 2)+ 1

primary是主分片数量,number_of_replicas是副本分片数量,假设一个索引,每个主分片有3个副本分片,那么quorum =(1+3)/2+1 = 3,往这个索引的主分片写入数据时,活跃的分片数至少为3才能写入成功,如果有两个副本分片失效,活跃分片数为1个主分片和1个副本分片。此时活跃分片数为2,那么此时就不允许向此分片写入数据。

可以通过配置文件index.write.wait_for_active_shards设置活跃分片数,也可以在请求中添加参数,默认是1,只要主分片可以即可写入。

详细信息可参考官方文档:

https://www.elastic.co/guide/en/elasticsearch/reference/6.1/docs-index_.html#index-wait-for-active-shards

2.路由算法

一般情况下,路由计算方式如下:

shard_num = hash(_routing) % num_primary_shards

_routing:默认情况下就是文档的id

num_primary_shards:主分片的数量

协调节点流程

  • 参数检查,遇到异常拒绝当前请求
  • 写入时,如果索引未创建,自动创建对应的index,具体在TransportBulkAction的doExecute方法中
  • 协调节点开始处理请求,入口为TransportBulkAction的executeBulk方法,之后进入TransportBulkAction的内部类BulkOperation中的doRun方法
  • doRun方法中,检查集群状态,如果集群有异常如Master节点不存在,写入请求会阻塞等待Master节点.
  • 从集群中获取集群的元数据信息metaData.
  • 遍历bulkRequest,从请求中获取每一个索引concreteIndex,判断请求类型,如果是写入操作,将请求转为IndexRequest,根据concreteIndex从metaData中获取该索引的元数据,之后获取索引的Mapping、创建版本号,并检查Mapping、ID等信息,如果ID为空将自动生成ID.
  • 再次遍历bulkRequest,将每一个请求重新封装为基于shard的请求列表,这么做是为了将路由到同一个分片的所有请求封装到同一个Request中。在这个过程中,会使用路由算法计算文档应该存储到哪个分片上,得到分片的ID,然后将写入到同一个分片的请求合并到同一个shardRequests中.
  • 遍历requestsByShard,里面记录了每个分片对应的所有写入请求,然后将分片请求封装为BulkShardRequest,等待有足够活跃的分片数,之后向分片执行请求,并在listener中等待响应,每个响应也是以shard为单位的,响应信息被设置到Response中.
  • 向分片转发请求具体的实现位于TransportReplicationAction中,转发前同样获取最新的集群状态,根据集群状态中的内容路由表找到目的shard对应主分片所在的节点,如果主分片在当前节点中,直接在本地执行,否则转发到相应的节点中执行.

TransportBulkAction

TransportBulkAction中BulkOperation的doRun方法解析用户请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
public class TransportBulkAction extends HandledTransportAction<BulkRequest, BulkResponse> {

@Override
protected void doExecute(Task task, BulkRequest bulkRequest, ActionListener<BulkResponse> listener) {
......

if (needToCheck()) {
// 获取请求中所有的索引
final Set<String> indices = bulkRequest.requests.stream()
.filter(request -> request.opType() != DocWriteRequest.OpType.DELETE
|| request.versionType() == VersionType.EXTERNAL
|| request.versionType() == VersionType.EXTERNAL_GTE)
.map(DocWriteRequest::index)
.collect(Collectors.toSet());
final Map<String, IndexNotFoundException> indicesThatCannotBeCreated = new HashMap<>();
Set<String> autoCreateIndices = new HashSet<>();
ClusterState state = clusterService.state();
// 遍历所有的索引
for (String index : indices) {
boolean shouldAutoCreate;
try {
// 是否自动创建索引
shouldAutoCreate = shouldAutoCreate(index, state);
} catch (IndexNotFoundException e) {
shouldAutoCreate = false;
indicesThatCannotBeCreated.put(index, e);
}
if (shouldAutoCreate) {
// 自动创建索引
autoCreateIndices.add(index);
}
}

......

} else {
executeBulk(task, bulkRequest, startTime, listener, responses, emptyMap());
}
}
private final class BulkOperation extends AbstractRunnable {
// 处理请求
protected void doRun() throws Exception {
// 检查集群状态,如果master节点不存在,会阻塞等待Master节点,甚至超时
final ClusterState clusterState = observer.setAndGetObservedState();
if (handleBlockExceptions(clusterState)) {
return;
}
final ConcreteIndices concreteIndices = new ConcreteIndices(clusterState, indexNameExpressionResolver);
// 获取集群元数据
MetaData metaData = clusterState.metaData();
// 遍历请求
for (int i = 0; i < bulkRequest.requests.size(); i++) {
DocWriteRequest docWriteRequest = bulkRequest.requests.get(i);
//the request can only be null because we set it to null in the previous step, so it gets ignored
if (docWriteRequest == null) {
continue;
}
if (addFailureIfIndexIsUnavailable(docWriteRequest, i, concreteIndices, metaData)) {
continue;
}
// 获取索引信息
Index concreteIndex = concreteIndices.resolveIfAbsent(docWriteRequest);
try {
// 判断操作类型
switch (docWriteRequest.opType()) {
case CREATE:
case INDEX://写入操作
// 转为IndexReqeust
IndexRequest indexRequest = (IndexRequest) docWriteRequest;
// 获取索引的元数据
final IndexMetaData indexMetaData = metaData.index(concreteIndex);
// 获取mapping的元数据
MappingMetaData mappingMd = indexMetaData.mappingOrDefault(indexRequest.type());
// 获取创建版本号
Version indexCreated = indexMetaData.getCreationVersion();
// 处理路由
indexRequest.resolveRouting(metaData);
// 检查mapping、id等信息
indexRequest.process(indexCreated, mappingMd, concreteIndex.getName());
break;
case UPDATE://更新操作
TransportUpdateAction.resolveAndValidateRouting(metaData, concreteIndex.getName(), (UpdateRequest) docWriteRequest);
break;
case DELETE://删除操作
docWriteRequest.routing(metaData.resolveIndexRouting(docWriteRequest.parent(), docWriteRequest.routing(), docWriteRequest.index()));
// check if routing is required, if so, throw error if routing wasn't specified
if (docWriteRequest.routing() == null && metaData.routingRequired(concreteIndex.getName(), docWriteRequest.type())) {
throw new RoutingMissingException(concreteIndex.getName(), docWriteRequest.type(), docWriteRequest.id());
}
break;
default: throw new AssertionError("request type not supported: [" + docWriteRequest.opType() + "]");
}
} catch (ElasticsearchParseException | IllegalArgumentException | RoutingMissingException e) {
BulkItemResponse.Failure failure = new BulkItemResponse.Failure(concreteIndex.getName(), docWriteRequest.type(), docWriteRequest.id(), e);
BulkItemResponse bulkItemResponse = new BulkItemResponse(i, docWriteRequest.opType(), failure);
responses.set(i, bulkItemResponse);
// make sure the request gets never processed again
bulkRequest.requests.set(i, null);
}
}

// 将用户的请求重新封装为基于shard的请求列表
Map<ShardId, List<BulkItemRequest>> requestsByShard = new HashMap<>();
for (int i = 0; i < bulkRequest.requests.size(); i++) {
DocWriteRequest request = bulkRequest.requests.get(i);
if (request == null) {
continue;
}
// 获取索引
String concreteIndex = concreteIndices.getConcreteIndex(request.index()).getName();
// 根据路由算法计算文档应该存储到哪个分片上,得到分片的ID
ShardId shardId = clusterService.operationRouting().indexShards(clusterState, concreteIndex, request.id(), request.routing()).shardId();
// 根据分片id判断是否已经存入到requestsByShard中,如果存在就取出放入shardRequests,如果不存在将当前的分片ID作为Key,创建一个空的ArrayList作为value
List<BulkItemRequest> shardRequests = requestsByShard.computeIfAbsent(shardId, shard -> new ArrayList<>());
// 当前封装的请求添加到shardRequests中,为了将路由到同一个分片的文档封装到一个shardRequest中
shardRequests.add(new BulkItemRequest(i, request));
}
// 如果requestsByShard为空
if (requestsByShard.isEmpty()) {
listener.onResponse(new BulkResponse(responses.toArray(new BulkItemResponse[responses.length()]), buildTookInMillis(startTimeNanos)));
return;
}

final AtomicInteger counter = new AtomicInteger(requestsByShard.size());
// 当前节点的id
String nodeId = clusterService.localNode().getId();
// 遍历requestsByShard
for (Map.Entry<ShardId, List<BulkItemRequest>> entry : requestsByShard.entrySet()) {
// 获取分片ID
final ShardId shardId = entry.getKey();
// 获取该分片ID对应的所有请求
final List<BulkItemRequest> requests = entry.getValue();
// 将请求封装为BulkShardRequest
BulkShardRequest bulkShardRequest = new BulkShardRequest(shardId, bulkRequest.getRefreshPolicy(),
requests.toArray(new BulkItemRequest[requests.size()]));
// 等待有足够活跃的分片数
bulkShardRequest.waitForActiveShards(bulkRequest.waitForActiveShards());
bulkShardRequest.timeout(bulkRequest.timeout());
if (task != null) {
bulkShardRequest.setParentTask(nodeId, task.getId());
}
// 向分片执行请求,在listener中等待响应
shardBulkAction.execute(bulkShardRequest, new ActionListener<BulkShardResponse>() {
@Override
public void onResponse(BulkShardResponse bulkShardResponse) {
for (BulkItemResponse bulkItemResponse : bulkShardResponse.getResponses()) {
// we may have no response if item failed
if (bulkItemResponse.getResponse() != null) {
bulkItemResponse.getResponse().setShardInfo(bulkShardResponse.getShardInfo());
}
responses.set(bulkItemResponse.getItemId(), bulkItemResponse);
}
if (counter.decrementAndGet() == 0) {
finishHim();
}
}

@Override
public void onFailure(Exception e) {
// create failures for all relevant requests
for (BulkItemRequest request : requests) {
final String indexName = concreteIndices.getConcreteIndex(request.index()).getName();
DocWriteRequest docWriteRequest = request.request();
responses.set(request.id(), new BulkItemResponse(request.id(), docWriteRequest.opType(),
new BulkItemResponse.Failure(indexName, docWriteRequest.type(), docWriteRequest.id(), e)));
}
if (counter.decrementAndGet() == 0) {
finishHim();
}
}

private void finishHim() {
listener.onResponse(new BulkResponse(responses.toArray(new BulkItemResponse[responses.length()]), buildTookInMillis(startTimeNanos)));
}
});
}
}
}
}

TransportReplicationAction

TransportReplicationAction的内部类ReroutePhase中的doRun方法向分片转发请求:

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
public abstract class TransportReplicationAction<
Request extends ReplicationRequest<Request>,
ReplicaRequest extends ReplicationRequest<ReplicaRequest>,
Response extends ReplicationResponse
> extends TransportAction<Request, Response> {

final class ReroutePhase extends AbstractRunnable {
@Override
protected void doRun() {
setPhase(task, "routing");
// 获取集群状态
final ClusterState state = observer.setAndGetObservedState();
if (handleBlockExceptions(state)) {
return;
}

// 获取请求中的索引
final String concreteIndex = concreteIndex(state);
// 获取索引元数据
final IndexMetaData indexMetaData = state.metaData().index(concreteIndex);
// 如果元数据为空
if (indexMetaData == null) {
retry(new IndexNotFoundException(concreteIndex));
return;
}
if (indexMetaData.getState() == IndexMetaData.State.CLOSE) {
throw new IndexClosedException(indexMetaData.getIndex());
}

// 等待足够活跃的分片数
resolveRequest(indexMetaData, request);
assert request.shardId() != null : "request shardId must be set in resolveRequest";
assert request.waitForActiveShards() != ActiveShardCount.DEFAULT : "request waitForActiveShards must be set in resolveRequest";
// 获取主分片所在节点
final ShardRouting primary = primary(state);
if (retryIfUnavailable(state, primary)) {
return;
}
final DiscoveryNode node = state.nodes().get(primary.currentNodeId());
// 如果主分片在本机节点,在本地执行
if (primary.currentNodeId().equals(state.nodes().getLocalNodeId())) {
performLocalAction(state, primary, node, indexMetaData);
} else {
// 转发到主分片所在节点
performRemoteAction(state, primary, node);
}
}

}

}

主分片节点流程

主分片所在的节点收到协调节点发送的请求后,开始执行写入操作,入口在ReplicationOperation中的execute方法中,写入成功后转发到副本分片,等待响应并回复协调节点。

  • 主分片在收到协调节点发送的请求后首先也做校验工作,检验是否是主分片,索引是否处于关闭状态等
  • 判断请求是否需要延迟执行
  • 判断主分片是否已经发生迁移
  • 检测活跃的shard数量是否足够,只要主分片可用就执行写入
  • 具体写入的入口在ReplicationOperation中的execute方法
  • 接下来进入TransportShardBulkAction的performOnPrimary方法(中间省略了一些步骤),继续省略一些调用过程,最后进入到InternalEngine的index方法,在这里将数据写入Lucene
  • 写入Lucene后将写入操作添加到translog,如果Lucene写入失败,需要对translog进行回滚
  • 根据配置的translog flush策略进行刷盘控制
  • 主分片写入完毕后转发给副本分片,副本分片执行写入操作,主分片等待副本分片的响应
  • 收到副本分片的全部响应后,执行finish,向协调节点返回消息,告之成功与失败的操作
  • 副本分片写入失败时,主分片所在节点将发送一个shardFaild请求给Master

ReplicationOperation

ReplicationOperation的execute方法是主分片写入操作的入口:

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
public class ReplicationOperation<
Request extends ReplicationRequest<Request>,
ReplicaRequest extends ReplicationRequest<ReplicaRequest>,
PrimaryResultT extends ReplicationOperation.PrimaryResult<ReplicaRequest>
> {

// 主分片写入操作入口
public void execute() throws Exception {
// 检查活跃分片数量
final String activeShardCountFailure = checkActiveShardCount();
final ShardRouting primaryRouting = primary.routingEntry();
final ShardId primaryId = primaryRouting.shardId();
if (activeShardCountFailure != null) {
finishAsFailed(new UnavailableShardsException(primaryId,
"{} Timeout: [{}], request: [{}]", activeShardCountFailure, request.timeout(), request));
return;
}

totalShards.incrementAndGet();
pendingActions.incrementAndGet(); // increase by 1 until we finish all primary coordination
// 开始执行写入操作
primaryResult = primary.perform(request);
// 更新分片的check point
primary.updateLocalCheckpointForShard(primaryRouting.allocationId().getId(), primary.localCheckpoint());
// 获取副本请求
final ReplicaRequest replicaRequest = primaryResult.replicaRequest();
if (replicaRequest != null) {
if (logger.isTraceEnabled()) {
logger.trace("[{}] op [{}] completed on primary for request [{}]", primaryId, opType, request);
}
// 全局check point
final long globalCheckpoint = primary.globalCheckpoint();
final ReplicationGroup replicationGroup = primary.getReplicationGroup();
markUnavailableShardsAsStale(replicaRequest, replicationGroup.getInSyncAllocationIds(), replicationGroup.getRoutingTable());
// 转发请求到副本分片
performOnReplicas(replicaRequest, globalCheckpoint, replicationGroup.getRoutingTable());
}

successfulShards.incrementAndGet(); // mark primary as successful
decPendingAndFinishIfNeeded();
}
}

TransportShardBulkAction

TransportShardBulkAction的performOnPrimary方法中主分片执行写入操作:

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
public class TransportShardBulkAction extends TransportWriteAction<BulkShardRequest, BulkShardRequest, BulkShardResponse> {
@Override
public WritePrimaryResult<BulkShardRequest, BulkShardResponse> shardOperationOnPrimary(
BulkShardRequest request, IndexShard primary) throws Exception {
return performOnPrimary(request, primary, updateHelper, threadPool::absoluteTimeInMillis, new ConcreteMappingUpdatePerformer());
}

// 主分片写入操作
public static WritePrimaryResult<BulkShardRequest, BulkShardResponse> performOnPrimary(
BulkShardRequest request,
IndexShard primary,
UpdateHelper updateHelper,
LongSupplier nowInMillisSupplier,
MappingUpdatePerformer mappingUpdater) throws Exception {
// 获取索引元数据
final IndexMetaData metaData = primary.indexSettings().getIndexMetaData();
Translog.Location location = null;
// 遍历请求
for (int requestIndex = 0; requestIndex < request.items().length; requestIndex++) {
if (isAborted(request.items()[requestIndex].getPrimaryResponse()) == false) {
// 执行具体的写入请求
location = executeBulkItemRequest(metaData, primary, request, location, requestIndex,
updateHelper, nowInMillisSupplier, mappingUpdater);
}
}
// 创建响应
BulkItemResponse[] responses = new BulkItemResponse[request.items().length];
BulkItemRequest[] items = request.items();
for (int i = 0; i < items.length; i++) {
responses[i] = items[i].getPrimaryResponse();
}
BulkShardResponse response = new BulkShardResponse(request.shardId(), responses);
return new WritePrimaryResult<>(request, response, location, null, primary, logger);
}
}

由于方法调用栈比较深,省略中间方法,直接看InternalEngine的index方法,省略的流程如下:

executeBulkItemRequest(TransportShardBulkAction)—>
executeIndexRequest(TransportShardBulkAction)—>
executeIndexRequestOnPrimary(TransportShardBulkAction)—>
applyIndexOperationOnPrimary(IndexShard)—>
applyIndexOperation(IndexShard)—>
index(IndexShard)—>
index(InternalEngine)

InternalEngine

InternalEngine的index方法将数据写入Luence,之后将写入操作添加到translog:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class InternalEngine extends Engine {
@Override
public IndexResult index(Index index) throws IOException {
assert Objects.equals(index.uid().field(), uidField) : index.uid().field();
final boolean doThrottle = index.origin().isRecovery() == false;
try (ReleasableLock releasableLock = readLock.acquire()) {
ensureOpen();
assert assertIncomingSequenceNumber(index.origin(), index.seqNo());
assert assertVersionType(index);
try (Releasable ignored = acquireLock(index.uid());

......

final IndexResult indexResult;
if (plan.earlyResultOnPreFlightError.isPresent()) {
indexResult = plan.earlyResultOnPreFlightError.get();
assert indexResult.hasFailure();
} else if (plan.indexIntoLucene) {
// 调用Lucene的写入接口将文档写入Lucene
indexResult = indexIntoLucene(index, plan);
} else {
indexResult = new IndexResult(
plan.versionForIndexing, plan.seqNoForIndexing, plan.currentNotFoundOrDeleted);
}
if (index.origin() != Operation.Origin.LOCAL_TRANSLOG_RECOVERY) {
final Translog.Location location;
if (indexResult.hasFailure() == false) {
// 将整个写入操作加入到translog
location = translog.add(new Translog.Index(index, indexResult));
} else if (indexResult.getSeqNo() != SequenceNumbers.UNASSIGNED_SEQ_NO) {
location = translog.add(new Translog.NoOp(indexResult.getSeqNo(), index.primaryTerm(), indexResult.getFailure().getMessage()));
} else {
location = null;
}
indexResult.setTranslogLocation(location);
}
......

return indexResult;
}
} catch (RuntimeException | IOException e) {
try {
maybeFailEngine("index", e);
} catch (Exception inner) {
e.addSuppressed(inner);
}
throw e;
}
}
}

GlobalCheckpointSyncAction

GlobalCheckpointSyncAction的maybeSyncTranslog方法进行刷盘控制:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class GlobalCheckpointSyncAction extends TransportReplicationAction<
GlobalCheckpointSyncAction.Request,
GlobalCheckpointSyncAction.Request,
ReplicationResponse> {

private void maybeSyncTranslog(final IndexShard indexShard) throws IOException {
final Translog translog = indexShard.getTranslog();
if (indexShard.getTranslogDurability() == Translog.Durability.REQUEST &&
translog.getLastSyncedGlobalCheckpoint() < indexShard.getGlobalCheckpoint()) {
indexShard.getTranslog().sync();
}
}
}

副本分片节点流程

副本分片的写入流程与主分片基本相同,写入完毕后向主分片发送响应。

参考:

Elasticsearch源码解析与优化实战【张超】

Elasticsearch源码分析-写入解析

Elasticsearch分布式一致性原理剖析(三)-Data篇

Elasticsearch版本:6.1.2

SpringMVC(三):HandlerMapping

Posted on 2018-12-22

继承关系图:

HandlerMapping的作用是根据请求URL找到对应的Handler也就是Controller。

HandlerMapping是一个接口,在接口中定义了一个getHandler方法,通过这个方法可以获得与HTTP请求对应的HandlerExecutionChain,这个HandlerExecutionChain中封装了具体的Controller对象,还设置了一个拦截器链,通过这个拦截器链中的拦截器可以为Handler对象提供功能的增强。

1
2
3
4
5
6
7
8
9
10
11
public interface HandlerMapping {
String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";
String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";
String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";
String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";
String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";
String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";

@Nullable
HandlerExecutionChain getHandler(HttpServletRequest var1) throws Exception;
}

一、Handler的注册

1.SimpleUrlHandlerMapping

以SimpleUrlHandlerMapping为例,看一下Hanlder的注册过程。

(1)持有了一个urlMap字段,保存URL和Hanlder的映射关系。

(2)Hanlder的注册过程是在initApplicationContext方法中调用的。initApplicationContext方法中先调用了父类AbstractUrlHandlerMapping 的initApplicationContext方法,这个方法中主要是对拦截器相关的设置。然后调用了registerHandlers方法注册handler。

(3)在registerHandlers方法中,调用了父类AbstractUrlHandlerMapping的registerHandler方法对handler进行注册。

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
public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping {
// 保存URL和Hanlder的映射关系
private final Map<String, Object> urlMap = new LinkedHashMap();

public SimpleUrlHandlerMapping() {
}

public void setMappings(Properties mappings) {
CollectionUtils.mergePropertiesIntoMap(mappings, this.urlMap);
}

public void setUrlMap(Map<String, ?> urlMap) {
this.urlMap.putAll(urlMap);
}

public Map<String, ?> getUrlMap() {
return this.urlMap;
}

// 初始化ApplicationContext
public void initApplicationContext() throws BeansException {
// 调用了AbstractHandlerMapping的initApplicationContext方法,这个方法主要初始化拦截器相关的东西
super.initApplicationContext();
// 注册handler
this.registerHandlers(this.urlMap);
}

// 注册handler,建立URL和controller之间的映射关系
protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
if(urlMap.isEmpty()) {
this.logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
} else {
// 获取所有的URL和对应的hanlder
urlMap.forEach((url, handler) -> {
if(!url.startsWith("/")) {
url = "/" + url;
}

if(handler instanceof String) {
handler = ((String)handler).trim();
}
// 调用父类的registerHandler完成注册
this.registerHandler(url, handler);
});
}

}
}
2.AbstractUrlHandlerMapping

(1)在AbstractUrlHandlerMapping中,同样持有了一个保存URL和Handler映射关系的字段handlerMap。

(2)在registerHandler方法中:

  • 首先设置一个变量resolvedHandler,将当前传入的handler赋给它;
  • 接着判断是否根据bean名称进行映射,如果是将会直接从容器中获取Handler赋给resolvedHandler;
  • 创建变量mappedHandler,表示是从handlerMap根据URL获取的Handler;如果mappedHandler不为空,会与从容器中根据bean获取的Handler对比是否一致,如果不一致将会报错。
  • 如果mappedHandler为空,说明Handler还未注册,会判断URL是否是’/‘或者’/*’,并分别设置到ROOT或者DefaultHandler中,如果只是普通的URL,因为还没有注册Handler,就把resolvedHandler注册到handlerMap中。
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
public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping implements MatchableHandlerMapping {

// 保存URL和Handler的映射关系,key为URL,value为对应的Handler也就是Controller
private final Map<String, Object> handlerMap = new LinkedHashMap();

// 根据url注册handler
protected void registerHandler(String[] urlPaths, String beanName) throws BeansException, IllegalStateException {
Assert.notNull(urlPaths, "URL path array must not be null");
String[] var3 = urlPaths;
int var4 = urlPaths.length;

for(int var5 = 0; var5 < var4; ++var5) {
String urlPath = var3[var5];
this.registerHandler((String)urlPath, (Object)beanName);
}

}

// 注册handler
protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
Assert.notNull(urlPath, "URL path must not be null");
Assert.notNull(handler, "Handler object must not be null");
Object resolvedHandler = handler;
// 使用bean名称进行映射
if(!this.lazyInitHandlers && handler instanceof String) {
String handlerName = (String)handler;
ApplicationContext applicationContext = this.obtainApplicationContext();
if(applicationContext.isSingleton(handlerName)) {
// 直接从容器中获取hanldler的bean,也就是controller
resolvedHandler = applicationContext.getBean(handlerName);
}
}
// 根据URL获取controller
Object mappedHandler = this.handlerMap.get(urlPath);
if(mappedHandler != null) { // 如果controller不为空
if(mappedHandler != resolvedHandler) {
throw new IllegalStateException("Cannot map " + this.getHandlerDescription(handler) + " to URL path [" + urlPath + "]: There is already " + this.getHandlerDescription(mappedHandler) + " mapped.");
}
} else if(urlPath.equals("/")) {// 如果url是"/"
if(this.logger.isInfoEnabled()) {
this.logger.info("Root mapping to " + this.getHandlerDescription(handler));
}
// 将"/"映射的controller设置到rootHandler
this.setRootHandler(resolvedHandler);
} else if(urlPath.equals("/*")) { // 如果是"/*"
if(this.logger.isInfoEnabled()) {
this.logger.info("Default mapping to " + this.getHandlerDescription(handler));
}
// 将"/*"映射的controller设置到defaultHandler
this.setDefaultHandler(resolvedHandler);
} else {
// 处理正常的URL映射,将当前传入设置handler的key和value,分别对应URL和映射的controller
this.handlerMap.put(urlPath, resolvedHandler);
if(this.logger.isInfoEnabled()) {
this.logger.info("Mapped URL path [" + urlPath + "] onto " + this.getHandlerDescription(handler));
}
}

}
}

二、Handler的查找过程

1.DispatcherServlet

回到DispatcherServlet,对HTTP请求的处理是在doService中完成的,那么就从这个方法入手,看一下DispatcherServlet是如何根据请求获取对应的Handler(Controller)处理HTTP请求的。

(1)在doService方法中会调用doDispatch方法,这里是分发请求的入口。

(2)在doDispatch方法中,调用了自己的getHandler根据请求获取对应的HandlerExecutionChain,在getHandler方法中遍历handlerMappings寻找对应的HandlerExecutionChain,具体的查找过程由子类实现,在子类的getHandler方法中完成。

1
2
// 根据请求得到对应的HandlerExecutionChain
mappedHandler = this.getHandler(processedRequest);
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
@Nullable
private List<HandlerMapping> handlerMappings;

// 获取handler的方法
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//遍历handlerMappings
if(this.handlerMappings != null) {
Iterator var2 = this.handlerMappings.iterator();

while(var2.hasNext()) {
HandlerMapping hm = (HandlerMapping)var2.next();
if(this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
}
//根据当前请求获取HandlerExecutionChain,这里的getHandler方法由子类实现
HandlerExecutionChain handler = hm.getHandler(request);
if(handler != null) {
return handler;
}
}
}

return null;
}

(3)HandlerExecutionChain获取成功后,会调用getHandlerAdapter方法获取HandlerAdapter,最后由HandlerAdapter调用handle方法处理请求。

1
2
3
4
5
6
7
8
//获取HandlerAdapter
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());

......


// 处理请求
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

整体代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
public class DispatcherServlet extends FrameworkServlet {

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
if(this.logger.isDebugEnabled()) {
String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult()?" resumed":"";
this.logger.debug("DispatcherServlet with name '" + this.getServletName() + "'" + resumed + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
}

Map<String, Object> attributesSnapshot = null;
if(WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap();
Enumeration attrNames = request.getAttributeNames();

label112:
while(true) {
String attrName;
do {
if(!attrNames.hasMoreElements()) {
break label112;
}

attrName = (String)attrNames.nextElement();
} while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));

attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}

request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());
if(this.flashMapManager != null) {
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if(inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
}

request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
}

try {
// 这里是分发请求的入口
this.doDispatch(request, response);
} finally {
if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {
this.restoreAttributesAfterInclude(request, attributesSnapshot);
}

}

}

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

try {
try {
// 这个ModelAndView持有handler处理请求的结果
ModelAndView mv = null;
Object dispatchException = null;

try {
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
// 根据请求得到对应的HandlerExecutionChain
mappedHandler = this.getHandler(processedRequest);
if(mappedHandler == null) {
this.noHandlerFound(processedRequest, response);
return;
}
//获取HandlerAdapter
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if(isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if(this.logger.isDebugEnabled()) {
this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}

if((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}

if(!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 处理请求
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if(asyncManager.isConcurrentHandlingStarted()) {
return;
}

this.applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler dispatch failed", var21);
}

this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
} catch (Exception var22) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
} catch (Throwable var23) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
}

} finally {
if(asyncManager.isConcurrentHandlingStarted()) {
if(mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if(multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}

}
}

@Nullable
private List<HandlerMapping> handlerMappings;

// 获取handler的方法
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
//遍历handlerMappings
if(this.handlerMappings != null) {
Iterator var2 = this.handlerMappings.iterator();

while(var2.hasNext()) {
HandlerMapping hm = (HandlerMapping)var2.next();
if(this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
}
//根据当前请求获取HandlerExecutionChain,这里的getHandler方法由子类实现
HandlerExecutionChain handler = hm.getHandler(request);
if(handler != null) {
return handler;
}
}
}

return null;
}

// 获取HandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if(this.handlerAdapters != null) {
Iterator var2 = this.handlerAdapters.iterator();

while(var2.hasNext()) {
HandlerAdapter ha = (HandlerAdapter)var2.next();
if(this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler adapter [" + ha + "]");
}

if(ha.supports(handler)) {
return ha;
}
}
}

throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
}

以SimpleControllerHandlerAdapter为例,看一下Adapter处理请求的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
public SimpleControllerHandlerAdapter() {
}

public boolean supports(Object handler) {
return handler instanceof Controller;
}

@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 处理HTTP请求
return ((Controller)handler).handleRequest(request, response);
}

public long getLastModified(HttpServletRequest request, Object handler) {
return handler instanceof LastModified?((LastModified)handler).getLastModified(request):-1L;
}
}
2.AbstractHandlerMapping

在上一步中,getHandler获取HandlerExecutionChain的过程由子类实现的,同样以SimpleUrlHandlerMapping为例,由继承关系图可知AbstractHandlerMapping是SimpleUrlHandlerMapping的父类,getHandler是在父类中实现的,那么就从AbstractHandlerMapping入手看一下AbstractHandlerMapping中是如何获取HandlerExecutionChain的。

(1)在getHandler方法中,首先调用了getHandlerInternal方法,获取Handler,这个方法是在AbstractUrlHandlerMapping中实现的。

(2)Handler获取之后,将Handler封装到了HandlerExecutionChain中并返回,HandlerExecutionChain中包含了Controller的定义和一个拦截器链。

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
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered {

@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 获取Handler
Object handler = this.getHandlerInternal(request);
// 使用默认的Handler
if(handler == null) {
handler = this.getDefaultHandler();
}

if(handler == null) {
return null;
} else {
if(handler instanceof String) {
// 根据bean名称从容器中获取handler
String handlerName = (String)handler;
handler = this.obtainApplicationContext().getBean(handlerName);
}
// 把handler封装到HandlerExecutionChain中
HandlerExecutionChain executionChain = this.getHandlerExecutionChain(handler, request);
if(CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = this.getCorsConfiguration(handler, request);
CorsConfiguration config = globalConfig != null?globalConfig.combine(handlerConfig):handlerConfig;
executionChain = this.getCorsHandlerExecutionChain(request, executionChain, config);
}

return executionChain;
}
}

// 获取HandlerExecutionChain
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = handler instanceof HandlerExecutionChain?(HandlerExecutionChain)handler:new HandlerExecutionChain(handler);
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
Iterator var5 = this.adaptedInterceptors.iterator();
// 添加拦截器
while(var5.hasNext()) {
HandlerInterceptor interceptor = (HandlerInterceptor)var5.next();
if(interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor)interceptor;
if(mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
} else {
chain.addInterceptor(interceptor);
}
}

return chain;
}
}

HandlerExecutionChain中的成员变量:

1
2
3
4
5
6
7
8
9
public class HandlerExecutionChain {
private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
// 处理请求的Controller
private final Object handler;
@Nullable
private HandlerInterceptor[] interceptors;
@Nullable
private List<HandlerInterceptor> interceptorList;
}
3.AbstractUrlHandlerMapping

(1)在AbstractUrlHandlerMapping中的getHandlerInternal方法中调用了lookupHandler方查找当前请求对应的Handler。

(2)查找Handler之后判断是否为空,如果为空,判断当前请求是否是”/“,如果是就使用RootHandler,如果RootHandler也为空,就使用默认的Handler.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping implements MatchableHandlerMapping {

// 获取Handler
@Nullable
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
// 从request中获取URL路径
String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request);
// 寻找URL对应的handler,如果没有找到,返回null
Object handler = this.lookupHandler(lookupPath, request);
if(handler == null) {
Object rawHandler = null;
// 如果是 "/"
if("/".equals(lookupPath)) {
rawHandler = this.getRootHandler();
}

if(rawHandler == null) {
rawHandler = this.getDefaultHandler();
}

if(rawHandler != null) {
if(rawHandler instanceof String) {
String handlerName = (String)rawHandler;
rawHandler = this.obtainApplicationContext().getBean(handlerName);
}
// 验证handler
this.validateHandler(rawHandler, request);
handler = this.buildPathExposingHandler(rawHandler, lookupPath, lookupPath, (Map)null);
}
}

if(handler != null && this.logger.isDebugEnabled()) {
this.logger.debug("Mapping [" + lookupPath + "] to " + handler);
} else if(handler == null && this.logger.isTraceEnabled()) {
this.logger.trace("No handler mapping found for [" + lookupPath + "]");
}

return handler;
}

// 根据URL寻找Handler
@Nullable
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
// 从map中获取handler
Object handler = this.handlerMap.get(urlPath);
if(handler != null) {
// 如果handler是bean名称,从容器中获取
if(handler instanceof String) {
String handlerName = (String)handler;
handler = this.obtainApplicationContext().getBean(handlerName);
}

this.validateHandler(handler, request);
return this.buildPathExposingHandler(handler, urlPath, urlPath, (Map)null);
} else {
List<String> matchingPatterns = new ArrayList();
Iterator var5 = this.handlerMap.keySet().iterator();

while(var5.hasNext()) {
String registeredPattern = (String)var5.next();
if(this.getPathMatcher().match(registeredPattern, urlPath)) {
matchingPatterns.add(registeredPattern);
} else if(this.useTrailingSlashMatch() && !registeredPattern.endsWith("/") && this.getPathMatcher().match(registeredPattern + "/", urlPath)) {
matchingPatterns.add(registeredPattern + "/");
}
}

String bestMatch = null;
Comparator<String> patternComparator = this.getPathMatcher().getPatternComparator(urlPath);
if(!matchingPatterns.isEmpty()) {
matchingPatterns.sort(patternComparator);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);
}

bestMatch = (String)matchingPatterns.get(0);
}

if(bestMatch != null) {
handler = this.handlerMap.get(bestMatch);
if(handler == null) {
if(bestMatch.endsWith("/")) {
handler = this.handlerMap.get(bestMatch.substring(0, bestMatch.length() - 1));
}

if(handler == null) {
throw new IllegalStateException("Could not find handler for best pattern match [" + bestMatch + "]");
}
}

String pathWithinMapping;
if(handler instanceof String) {
pathWithinMapping = (String)handler;
handler = this.obtainApplicationContext().getBean(pathWithinMapping);
}

this.validateHandler(handler, request);
pathWithinMapping = this.getPathMatcher().extractPathWithinPattern(bestMatch, urlPath);
Map<String, String> uriTemplateVariables = new LinkedHashMap();
Iterator var9 = matchingPatterns.iterator();

while(var9.hasNext()) {
String matchingPattern = (String)var9.next();
if(patternComparator.compare(bestMatch, matchingPattern) == 0) {
Map<String, String> vars = this.getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
Map<String, String> decodedVars = this.getUrlPathHelper().decodePathVariables(request, vars);
uriTemplateVariables.putAll(decodedVars);
}
}

if(this.logger.isDebugEnabled()) {
this.logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
}

return this.buildPathExposingHandler(handler, bestMatch, pathWithinMapping, uriTemplateVariables);
} else {
return null;
}
}
}
}

参考:

spring技术内幕:深入解析spring架构与设计原理

SpringMvc的handlerMapping的源码解读

SpringMVC工作原理之二:HandlerMapping和HandlerAdapter

Spring版本:5.0.5

SpringMVC(二):DispatcherServlet对SpringMVC的初始化

Posted on 2018-12-21

在SpringMVC项目中除了spring容器(根上下文),DispatcherServlet也会建立一个自己的IoC容器来持有springmvc的bean对象,在建立这个容器时,会从ServletContext中获取根上下文作为自己的双亲上下文,它可获取双亲上下文中的bean,DispatcherServlet的IoC容器也会存到ServletContext中。

DispatcherServlet是一个servlet,回想servlet的生命周期,servlet在初始化的时候调用的是init方法,那么就从init方法开始看一下DispatcherServlet对SpringMVC的初始化。

继承关系图:

1.HttpServletBean

HttpServletBean是DispatcherServlet的父类,init方法是在HttpServletBean中实现的。

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
public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware {

public final void init() throws ServletException {
if(this.logger.isDebugEnabled()) {
this.logger.debug("Initializing servlet '" + this.getServletName() + "'");
}
//获取servlet初始化参数
PropertyValues pvs = new HttpServletBean.ServletConfigPropertyValues(this.getServletConfig(), this.requiredProperties);
if(!pvs.isEmpty()) {
try {
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new ServletContextResourceLoader(this.getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.getEnvironment()));
this.initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
} catch (BeansException var4) {
if(this.logger.isErrorEnabled()) {
this.logger.error("Failed to set bean properties on servlet '" + this.getServletName() + "'", var4);
}

throw var4;
}
}
// 初始化,在FrameworkServlet中实现
this.initServletBean();
if(this.logger.isDebugEnabled()) {
this.logger.debug("Servlet '" + this.getServletName() + "' configured successfully");
}
}

}

HttpServletBean除了获取servlet初始化参数,还调用了initServletBean方法,进行具体的初始化,这个方法是在FrameworkServlet中实现的。

2.FrameworkServlet

FrameworkServlet同样是DispatcherServlet的父类。

DispatcherServlet的IoC容器的初始化

在initServletBean方法中,调用了initWebApplicationContext方法来初始化IoC容器,在初始化容器的方法中:

  1. 首先从ServletContext中获取了根上下文,然后判断DispatcherServlet的容器wac是否为空,如果不为空就将根上下文设置为双亲上下文,然后调用configureAndRefreshWebApplicationContext方法,完成容器的初始化。

  2. 如果容器为空,就调用createWebApplicationContext创建容器,默认使用的是XmlWebApplicationContext,创建容器的时候将根上下文作为参数传入,创建之后同样将根上下文设置为双亲上下文。

  3. DispatcherServlet的容器也会被设置到SerletContext中,使用的属性名是和
    当前Servlet的名称。

  4. 在createWebApplicationContext创建容器的方法中,最后调用了configureAndRefreshWebApplicationContext方法,在该方法中调用了容器的refresh方法,之后就与spring IoC容器的初始化过程一致了。

之后,SpringMVC的上下文就建立起来了,意味着DispatcheServlet拥有自己的Bean定义空间,为使用各个独立的XML文件来配置MVC中的各个bean创建了条件。

SpringMVC的初始化

在initWebApplicationContext方法中,在容器创建完成后,有一步是调用this.onRefresh方法,这个方法是在DispatcherSerlet中实现的,在该方法中完成了SpringMVC的初始化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
protected final void initServletBean() throws ServletException {
this.getServletContext().log("Initializing Spring FrameworkServlet '" + this.getServletName() + "'");
if(this.logger.isInfoEnabled()) {
this.logger.info("FrameworkServlet '" + this.getServletName() + "': initialization started");
}

long startTime = System.currentTimeMillis();

try {
// 初始化容器
this.webApplicationContext = this.initWebApplicationContext();
this.initFrameworkServlet();
} catch (RuntimeException | ServletException var5) {
this.logger.error("Context initialization failed", var5);
throw var5;
}

if(this.logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime;
this.logger.info("FrameworkServlet '" + this.getServletName() + "': initialization completed in " + elapsedTime + " ms");
}

}
// 初始化容器
protected WebApplicationContext initWebApplicationContext() {
// 获取根上下文
WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
// DispatchServlet的容器
WebApplicationContext wac = null;
// 如果不为空
if(this.webApplicationContext != null) {
wac = this.webApplicationContext;
if(wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)wac;
if(!cwac.isActive()) {
if(cwac.getParent() == null) {
// 将根上下文设置为当前容器的双亲
cwac.setParent(rootContext);
}

this.configureAndRefreshWebApplicationContext(cwac);
}
}
}

if(wac == null) {
wac = this.findWebApplicationContext();
}

if(wac == null) {
// 如果dispatchServlet的容器为空,创建容器
wac = this.createWebApplicationContext(rootContext);
}

if(!this.refreshEventReceived) {
// 在DispatcherServlet中实现了该方法,完成springMVC的初始化
this.onRefresh(wac);
}

if(this.publishContext) {
String attrName = this.getServletContextAttributeName();
// 将创建好的容器设置到ServletContext
this.getServletContext().setAttribute(attrName, wac);
if(this.logger.isDebugEnabled()) {
this.logger.debug("Published WebApplicationContext of servlet '" + this.getServletName() + "' as ServletContext attribute with name [" + attrName + "]");
}
}

return wac;
}


protected WebApplicationContext createWebApplicationContext(@Nullable WebApplicationContext parent) {
return this.createWebApplicationContext((ApplicationContext)parent);
}

// 创建容器
protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {
// 获取ContextClass
Class<?> contextClass = this.getContextClass();
if(this.logger.isDebugEnabled()) {
this.logger.debug("Servlet with name '" + this.getServletName() + "' will try to create custom WebApplicationContext context of class '" + contextClass.getName() + "', using parent context [" + parent + "]");
}

if(!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
throw new ApplicationContextException("Fatal initialization error in servlet with name '" + this.getServletName() + "': custom WebApplicationContext class [" + contextClass.getName() + "] is not of type ConfigurableWebApplicationContext");
} else {
//创建容器,默认使用的是XmlWebApplicationContext
ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass);
wac.setEnvironment(this.getEnvironment());
// 这里同样将根上下文作为当前容器的双亲上下文
wac.setParent(parent);
String configLocation = this.getContextConfigLocation();
if(configLocation != null) {
wac.setConfigLocation(configLocation);
}
// 配置并刷新容器
this.configureAndRefreshWebApplicationContext(wac);
return wac;
}
}

// 配置并初始化容器
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
if(ObjectUtils.identityToString(wac).equals(wac.getId())) {
if(this.contextId != null) {
wac.setId(this.contextId);
} else {
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(this.getServletContext().getContextPath()) + '/' + this.getServletName());
}
}
// 设置ServletContext
wac.setServletContext(this.getServletContext());
wac.setServletConfig(this.getServletConfig());
wac.setNamespace(this.getNamespace());
wac.addApplicationListener(new SourceFilteringListener(wac, new FrameworkServlet.ContextRefreshListener(null)));
ConfigurableEnvironment env = wac.getEnvironment();
if(env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment)env).initPropertySources(this.getServletContext(), this.getServletConfig());
}

this.postProcessWebApplicationContext(wac);
this.applyInitializers(wac);
// 调用容器的refresh方法
wac.refresh();
}
WebApplicationContextUtils

取得根上下文的过程是在WebApplicationContextUtils中实现的。在getWebApplicationContext方法中,先调用WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE获取根上下文在ServletContext中的属性名,然后从ServletContext中获取根上下文,转换为WebApplicationContext返回。

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
public abstract class WebApplicationContextUtils {
private static final boolean jsfPresent = ClassUtils.isPresent("javax.faces.context.FacesContext", RequestContextHolder.class.getClassLoader());

public WebApplicationContextUtils() {
}

//获取根上下文
public static WebApplicationContext getRequiredWebApplicationContext(ServletContext sc) throws IllegalStateException {
// 获取根上下文
WebApplicationContext wac = getWebApplicationContext(sc);
if(wac == null) {
throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");
} else {
return wac;
}
}

@Nullable
public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
// 从servlet中获取根上下文
return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}

@Nullable
public static WebApplicationContext getWebApplicationContext(ServletContext sc, String attrName) {
Assert.notNull(sc, "ServletContext must not be null");
// 从servlet中根据属性名获取根上下文
Object attr = sc.getAttribute(attrName);
if(attr == null) {
return null;
} else if(attr instanceof RuntimeException) {
throw (RuntimeException)attr;
} else if(attr instanceof Error) {
throw (Error)attr;
} else if(attr instanceof Exception) {
throw new IllegalStateException((Exception)attr);
} else if(!(attr instanceof WebApplicationContext)) {
throw new IllegalStateException("Context attribute is not of type WebApplicationContext: " + attr);
} else {
// 返回根上下文
return (WebApplicationContext)attr;
}
}
}

3.DispatcherServlet

在FrameworkServlet的configureAndRefreshWebApplicationContext方法中,最后一步是调用onRefresh方法,这个方法是在DispatchServlet中实现的。

在onRefresh方法中,调用了initStrategies方法,这个方法中启动了SpringMVC框架的初始化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class DispatcherServlet extends FrameworkServlet {
protected void onRefresh(ApplicationContext context) {
this.initStrategies(context);
}

protected void initStrategies(ApplicationContext context) {
this.initMultipartResolver(context);
this.initLocaleResolver(context);
this.initThemeResolver(context);
// 初始化HanlderMappings
this.initHandlerMappings(context);
this.initHandlerAdapters(context);
this.initHandlerExceptionResolvers(context);
this.initRequestToViewNameTranslator(context);
this.initViewResolvers(context);
this.initFlashMapManager(context);
}
}

以HandlerMapping为例,HandlerMapping是为HTTP请求寻找对应的Controller控制器,在HandlerMapping初始化过程中,从IoC容器中获取在配置文件中配置好的,以HandlerMapping为例:

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
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
// 导入所有的HandlerMapping Bean,默认从所有的容器中获取
if(this.detectAllHandlerMappings) {
Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if(!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList(matchingBeans.values());
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
} else {
try {
// 根据名称从当前的容器中获取
HandlerMapping hm = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
} catch (NoSuchBeanDefinitionException var3) {
;
}
}
// 如果没有找到handlerMapping,设置默认的handlerMapping
if(this.handlerMappings == null) {
this.handlerMappings = this.getDefaultStrategies(context, HandlerMapping.class);
if(this.logger.isDebugEnabled()) {
this.logger.debug("No HandlerMappings found in servlet '" + this.getServletName() + "': using default");
}
}

}

参考:

spring技术内幕:深入解析spring架构与设计原理

Spring版本:5.0.5

SpringMVC(一):Web环境中的IoC容器启动过程

Posted on 2018-12-16

在springmvc项目中,可以有多个容器,而且容器有上下层关系,此处的容器指的是spring容器,它是springmvc的父容器,springmvc容器将在下一章讲解。

WebApplicationContext

web环境下spring默认使用的是WebApplicationContext,它是一个接口,看一下WebApplicationContext的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface WebApplicationContext extends ApplicationContext {
// 用于在ServletContext取根上下文
String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
String SCOPE_REQUEST = "request";
String SCOPE_SESSION = "session";
String SCOPE_APPLICATION = "application";
String SERVLET_CONTEXT_BEAN_NAME = "servletContext";
String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";
String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";

// 获取ServletContext
@Nullable
ServletContext getServletContext();
}

(1)WebApplicationContext接口本身中的内容并不多,可以看到它继承了ApplicationContext,有一个ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE成员变量,这个变量用于将IoC容器设置到ServletContext时的key,之后就可以从ServletContext中获取IoC容器。

1
servletContext.setAttribute(WebApplicationConservletContexttext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

(2)既然WebApplicationContext只是一个接口,那么一定有一个它的实现类,作为IoC容器的实现,这个类就是XmlWebApplicationContext。

XmlWebApplicationContext

Spring使用XmlWebApplicationContext作为默认的WebApplicationContext容器实现,从继承关系中可以看到,XmlWebApplicationContext继承了WebApplicationContext,其实从名字上就可以看出,XmlWebApplicationContext也是ApplicationContext容器的实现,在ApplicationContext的基础之上,增加了对Web环境和XML配置定义的处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {
// 默认的配置文件applicationContext.xml,在WEB-INF目录下
public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
// web项目的WEB-INF目录
public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";

public XmlWebApplicationContext() {
}

// 加载BeanDefinition的方法,在容器refresh()时启动
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// XmlBeanDefinitionReader对象,解析xml文件使用
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.setEnvironment(this.getEnvironment());
// 设置ResourceLoader,XmlWebApplicationContext是DefaultResource的子类,同样使用DefaultResourceLoader对资源文件定位
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
this.initBeanDefinitionReader(beanDefinitionReader);
// 载入BeanDefinition
this.loadBeanDefinitions(beanDefinitionReader);
}

protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) {
}

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
// 获取资源文件的地址
String[] configLocations = this.getConfigLocations();
if(configLocations != null) {
String[] var3 = configLocations;
int var4 = configLocations.length;

for(int var5 = 0; var5 < var4; ++var5) {
String configLocation = var3[var5];
// 根据资源文件的地址由XmlBeanDefinitionReader解析文件并载入BeanDefinition
reader.loadBeanDefinitions(configLocation);
}
}

}

// 获取默认的配置
protected String[] getDefaultConfigLocations() {
return this.getNamespace() != null?new String[]{"/WEB-INF/" + this.getNamespace() + ".xml"}:new String[]{"/WEB-INF/applicationContext.xml"};
}
}

从XmlWebApplicationContext的启动过程来看,与IoC容器的初始化过程基本差不多,只不过在Web环境中,已经定义好了一个默认的配置文件,即WEB-INF/appicationContext.xml,下面看一下如何进入到XmlWebApplicationContext的loadBeanDefinitions方法中的。

ContextLoaderListener

ContextLoaderListener是Web容器中配置的监听器,WebApplicationContext容器的载入就是它负责的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
public ContextLoaderListener() {
}

public ContextLoaderListener(WebApplicationContext context) {
super(context);
}

public void contextInitialized(ServletContextEvent event) {
// 初始化WebApplicationContext,具体的工作在ContextLoader中完成
this.initWebApplicationContext(event.getServletContext());
}

public void contextDestroyed(ServletContextEvent event) {
// 销毁WebApplicationContext
this.closeWebApplicationContext(event.getServletContext());
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}
}

ContextLoaderListener的contextInitialized方法中调用了initWebApplicationContext方法初始化web容器,该方法是在它的父类ContextLoader中实现的。

ContextLoader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
public class ContextLoader {

// Web IoC容器,也称作根上下文
@Nullable
private WebApplicationContext context;

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
// 判断根上下文是否已经存在
if(servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
throw new IllegalStateException("Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!");
} else {
Log logger = LogFactory.getLog(ContextLoader.class);
servletContext.log("Initializing Spring root WebApplicationContext");
if(logger.isInfoEnabled()) {
logger.info("Root WebApplicationContext: initialization started");
}

long startTime = System.currentTimeMillis();

try {
if(this.context == null) {
// 创建容器WebApplicationContext
this.context = this.createWebApplicationContext(servletContext);
}
//如果容器是ConfigurableWebApplicationContext的一个实现
if(this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)this.context;
if(!cwac.isActive()) {
// 如果双亲为空
if(cwac.getParent() == null) {
// 加载根上下文的双亲上下文
ApplicationContext parent = this.loadParentContext(servletContext);
cwac.setParent(parent);
}
// 配置并refresh根上下文
this.configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}
// 将当前创建的web IoC容器context设置为servletContext的根上下文
servletContext.setAttribute(WebApplicationConservletContexttext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
if(ccl == ContextLoader.class.getClassLoader()) {
currentContext = this.context;
} else if(ccl != null) {
currentContextPerThread.put(ccl, this.context);
}

if(logger.isDebugEnabled()) {
logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
}

if(logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime;
logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
}

return this.context;
} catch (RuntimeException var8) {
logger.error("Context initialization failed", var8);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var8);
throw var8;
} catch (Error var9) {
logger.error("Context initialization failed", var9);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var9);
throw var9;
}
}
}

/**
* 创建web容器的地方
*/
protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
// 判断使用什么样的类作为Web环境中的IoC容器
Class<?> contextClass = this.determineContextClass(sc);
if(!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
throw new ApplicationContextException("Custom context class [" + contextClass.getName() + "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
} else {
// 根据类信息实例化web IoC容器
return (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass);
}
}

/**
* 判断使用哪种web容器
*/
protected Class<?> determineContextClass(ServletContext servletContext) {
// 读取在ServletContext中对contextClass参数的配置
String contextClassName = servletContext.getInitParameter("contextClass");
// 如果在ServletContext中对contextClass参数配置不为空
if(contextClassName != null) {
try {
// 返回类信息
return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
} catch (ClassNotFoundException var4) {
throw new ApplicationContextException("Failed to load custom context class [" + contextClassName + "]", var4);
}
} else {
// 如果配置信息为空,使用默认的WebApplicationContext
contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());

try {
return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
} catch (ClassNotFoundException var5) {
throw new ApplicationContextException("Failed to load default context class [" + contextClassName + "]", var5);
}
}
}

/**
* 配置并refresh,这个方法中调用了容器的refresh方法来完成Web环境下IoC容器的初始化
*/
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
String configLocationParam;
if(ObjectUtils.identityToString(wac).equals(wac.getId())) {
configLocationParam = sc.getInitParameter("contextId");
if(configLocationParam != null) {
wac.setId(configLocationParam);
} else {
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath()));
}
}
// 为容器设置ServletContext
wac.setServletContext(sc);
configLocationParam = sc.getInitParameter("contextConfigLocation");
if(configLocationParam != null) {
wac.setConfigLocation(configLocationParam);
}

ConfigurableEnvironment env = wac.getEnvironment();
if(env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment)env).initPropertySources(sc, (ServletConfig)null);
}

this.customizeContext(sc, wac);
// 调用容器的refresh方法,完成容器的初始化
wac.refresh();
}
}
  1. 在ContextLoader类中,存在一个WebApplicationContext类型的字段context, 这个变量就是Web环境中的IoC容器,也会配置在ServletContext的根上下文中,ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE为属性名,已经在WebApplication中定义为了一个常量。

  2. initWebApplicationContext方法,是启动IoC容器的入口:

    (1)如果容器还没有创建,会调用createWebApplicationContext方法创建IoC容器,在该方法中,会调用determineContextClass方法判断使用哪种IoC容器,如果没有设置contextClass参数,就使用默认的容器即WebApplicationContext。

    (2)接着会判断创建的容器是否是ConfigurableWebApplicationContext的实例,如果是,将设置双亲上下文,并调用configureAndRefreshWebApplicationContext方法,将当前的serveltContext设置到Ioc容器中,最后调用容器的refresh()方法,完成容器的初始化。

    (3)最后会把容器设置到ServletContext的根上下文中,并将容器返回。

AbstractApplicationContext

再回顾一下XmlWebApplicationContext的继承关系,它继承了AbstractRefreshableApplicationContext,AbstractRefreshableApplicationContext又继承了AbstractApplicationContext方法,refresh方法就是在AbstractApplicationContext实现的,之后的流程就和IoC容器启动过程一样了。

AbstractApplicationContext中的refresh()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {

public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
// 调用AbstractRefreshableApplicationContext的prepareBeanFactory方法
this.prepareBeanFactory(beanFactory);

try {
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var9) {
if(this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}

this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}

}
}
}

AbstractRefreshableApplicationContext

refresh方法中调用了调用AbstractRefreshableApplicationContext的prepareBeanFactory方法,在该方法中对BeanDefinition进行了载入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
protected final void refreshBeanFactory() throws BeansException {
if(this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());
this.customizeBeanFactory(beanFactory);
// 载入BeanDefinition
this.loadBeanDefinitions(beanFactory);
Object var2 = this.beanFactoryMonitor;
synchronized(this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException var5) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
}
}
}

到此,如何进入到XmlWebApplicationContext的loadBeanDefinitions方法中的过程已经很明了了。

参考:

spring技术内幕:深入解析spring架构与设计原理

Spring和SpringMVC父子容器关系初窥

Spring版本:5.0.5

AOP原理(二):AopProxy拦截机制

Posted on 2018-07-08

以JDK动态代理为例,看一下Aop代理的拦截机制:

JdkDynamicAopProxy的invoke拦截

使用JDK动态代理生成代理对象时,需要传入三个参数,分别是目标对象的类加载器loader、目标对象的接口interfaces、一个InvocationHandler对象:

1
2
3
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)

InvocationHandler是一个接口,定义了一个invoke方法,对目标对象方法调用的拦截就是在invoke方法中实现的。

1
2
3
4
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}

JdkDynamicAopProxy

1.拦截器链的调用

JdkDynamicAopProxy实现了InvocationHandler接口,因此生成代理对象时,可以将自身作为参数传入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//使用JDK动态代理生成代理对象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

/**
* InvocationHandler接口invoke方法的实现
*/
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;

TargetSource targetSource = this.advised.targetSource;
Object target = null;

try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// 如果目标对象没有实现Object的equals方法
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// 目标对象没有实现hashcode方法
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
//根据代理对象的配置来调用服务
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}

Object retVal;

if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}

// 获取目标对象
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);

// 获取该方法的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

// 如果没有拦截器,直接调用目标对象的方法
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
//创建一个ReflectiveMethodInvocation对象,调用拦截器之后再调用目标对象的方法
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 沿着拦截器链继续前进
retVal = invocation.proceed();
}

// 处理方法返回值
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
}

(1)在invoke方法中,如果没有配置拦截器,将会通过AopUtils的invokeJoinpointUsingReflection方法,使用反射机制对目标对象的方法进行调用。

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
public abstract class AopUtils  {
/**
* 通过反射执行目标对象的方法
*/
@Nullable
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
throws Throwable {

// 使用反射机制调用目标对象的方法
try {
ReflectionUtils.makeAccessible(method);
return method.invoke(target, args);
}
catch (InvocationTargetException ex) {
// Invoked method threw a checked exception.
// We must rethrow it. The client won't see the interceptor.
throw ex.getTargetException();
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
method + "] on target [" + target + "]", ex);
}
catch (IllegalAccessException ex) {
throw new AopInvocationException("Could not access method [" + method + "]", ex);
}
}
}

(2)如果配置了拦截器,会获创建一个ReflectiveMethodInvocation对象,通过ReflectiveMethodInvocation对象的proceed方法逐个运行拦截器的拦截方法,从而完成整个拦截器链的调用。当拦截器链执行完毕后,同样使用反射机制执行目标对象中的方法。
在运行拦截器的拦截方法之前,会进行动态匹配判断,判断是否和定义的pointcut匹配,如果匹配就会执行这个advice。

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
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
@Override
@Nullable
public Object proceed() throws Throwable {
// 如果拦截器链调用完毕
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//这里依旧使用AopUtils的invokeJoinpointUsingReflection方法使用反射机制完成目标对象方法的调用
return invokeJoinpoint();
}
//获取定义的拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//如果是InterceptorAndDynamicMethodMatcher的实例
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {

InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
// 对拦截器进行动态匹配判断,如果和定义的切点匹配,将会执行这个advice
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
//执行拦截器的方法
return dm.interceptor.invoke(this);
}
else {
//如果未匹配,继续拦截器链中的下一个拦截器
return proceed();
}
}
else {
// 如果是一个拦截器,直接调用该拦截器对应的方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}

/**
* 调用目标对象的方法
*/
@Nullable
protected Object invokeJoinpoint() throws Throwable {
//同样使用反射执行方法
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
}

2.配置通知器

回到JdkDynamicAopProxy的ivoke方法中,有一个获取当前方法的拦截器链的过程:

1
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

getInterceptorsAndDynamicInterceptionAdvice方法是在AdvisedSupport类中实现的,在这个方法中,还使用到了缓存:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class AdvisedSupport extends ProxyConfig implements Advised {
/**
* 从配置中获取拦截器
*/
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
//使用了缓存
MethodCacheKey cacheKey = new MethodCacheKey(method);
//从缓存中获取拦截器
List<Object> cached = this.methodCache.get(cacheKey);
//如果缓存中不存在
if (cached == null) {
// 使用advisorChainFactory获取拦截器链
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
}

如果缓存中不存在拦截器链,会调用AdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法获取拦截器链,AdvisorChainFactory是一个生产通知器链的工厂:

1
2
3
4
public interface AdvisorChainFactory {
List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass);

}

AdvisorChainFactory是一个接口,它的子类DefaultAdvisorChainFactory实现了该方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {

@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {

// 根据配置中通知器的个数设置list的长度
List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
//用到了适配器模式,通过适配器加入拦截器链
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
//遍历通知器集合
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
//通知器转为对应的拦截器
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
//判断是否匹配
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) {
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}

return interceptorList;
}
}

来看这行代码,从GlobalAdvisorAdapterRegistry类中获取了通知适配器注册实例AdvisorAdapterRegistry:

1
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
GlobalAdvisorAdapterRegistry

GlobalAdvisorAdapterRegistry是一个抽象类,返回的是一个单例模式的DefaultAdvisorAdapterRegistry对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public abstract class GlobalAdvisorAdapterRegistry {

/**
* 单例模式,使用了DefaultAdvisorAdapterRegistry实现
*/
private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();

/**
* 返回实例
*/
public static AdvisorAdapterRegistry getInstance() {
return instance;
}

/**
* 重置
*/
static void reset() {
instance = new DefaultAdvisorAdapterRegistry();
}

}

DefaultAdvisorAdapterRegistry

DefaultAdvisorAdapterRegistry在构造方法中注册了一系列的适配器,在getInterceptors方法中通过适配器模式完成了advice向拦截器的转换:

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
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

private final List<AdvisorAdapter> adapters = new ArrayList<>(3);

/**
* 构造函数,注册适配器
*/
public DefaultAdvisorAdapterRegistry() {
//前置通知
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}


@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}

/**
* 获取拦截器
*/
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
//创建一个list,存放的类型是MethodInterceptor
List<MethodInterceptor> interceptors = new ArrayList<>(3);
//从Advisor通知器配置中获取advice通知
Advice advice = advisor.getAdvice();
//如果是MethodInterceptor类型的,不需要适配器,直接加入拦截器集合中
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
//这里判断取得的advice是什么类型的通知器,从而注册不同的拦截器
if (adapter.supportsAdvice(advice)) {
//advice转为拦截器加入到集合
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}

@Override
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}

}

getInterceptors方法中,传入的参数是Advisor类型的通知,返回的是方法拦截器集合,每个通知器都有对应的方法拦截器,比如BeforeAdvice通知器的拦截器是MethodBeforeAdviceInterceptor,该方法的作用就是通过适配器模式将通知器转为对应的方法拦截器。所以通知器如果是MethodInterceptor类型的直接加入集合,如果不是,需要通过适配器模式将通知转为拦截器:

1
2
3
4
5
6
7
for (AdvisorAdapter adapter : this.adapters) {
//这里判断取得的advice是什么类型的通知器,从而注册不同的拦截器
if (adapter.supportsAdvice(advice)) {
//通过适配器模式advice转为拦截器加入到集合
interceptors.add(adapter.getInterceptor(advisor));
}
}

Spring AOP适配器模式的应用

1.AdvisorAdapter

上面知道通过调用AdvisorAdapter的getInterceptor方法将通知器advisor转为了对应的拦截器MethodInterceptor,AdvisorAdapter是一个接口,定义了两个方法,分别是
supportsAdvice和getInterceptor:

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface AdvisorAdapter {

/**
* 判断通知器的类型是否支持
*/
boolean supportsAdvice(Advice advice);

/**
* advisor转为MethodInterceptor
*/
MethodInterceptor getInterceptor(Advisor advisor);

}
MethodInterceptor
1
2
3
4
5
6
@FunctionalInterface
public interface MethodInterceptor extends Interceptor {

Object invoke(MethodInvocation invocation) throws Throwable;

}
2.MethodBeforeAdviceAdapter

以MethodBeforeAdviceAdapter为例看一下如何转换的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

@Override
public boolean supportsAdvice(Advice advice) {
//判断通知器是否是MethodBeforeAdvice的实例
return (advice instanceof MethodBeforeAdvice);
}

@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
//通知器转为MethodBeforeAdvice类型
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
//MethodBeforeAdvice转为MethodBeforeAdviceInterceptor类型
return new MethodBeforeAdviceInterceptor(advice);
}

}
MethodBeforeAdviceInterceptor

MethodBeforeAdviceInterceptor实现了MethodInterceptor接口,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

private MethodBeforeAdvice advice;


/**
* 构造函数
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}

/**
* 拦截器的回调方法,会在代理对象的方法被调用前调用
*/
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}

}

参考:

spring技术内幕:深入解析spring架构与设计原理

jzq114:AOP源码分析之初始化通知器链

峰峰峰峰峰:一起学设计模式 - 适配器模式

Spring版本:5.0.5

AOP原理(一):AopProxy代理对象的生成

Posted on 2018-07-01

前提知识:动态代理

岑宇:Java的三种代理模式

孤傲苍狼:Java基础加强总结(三)——代理(Proxy)

基于接口的配置方式

基于接口的配置方式比较古老,但是有利于熟悉源码。

一个简单的例子:

1.StudentService接口,里面包含了一个save方法:

1
2
3
public interface  StudentService {
void save();
}

2.StudentService接口实现类StduentServiceImpl,它实现了save方法,里面只是简单的打印了一句话:

1
2
3
4
5
6
7
public class StudentServiceImpl implements StudentService{

@Override
public void save() {
System.out.println("执行save方法");
}
}

3.一个自定义前置通知器MyBeforeAdvide,它实现了方法前置通知器接口MethodBeforeAdvice,重写了before方法:

1
2
3
4
5
6
7
public class MyBeforeAdvice implements MethodBeforeAdvice {

@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("准备调用方法:" + method.getName());
}
}

4.创建spring-aop.xml配置文件,添加以下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd ">

<!--配置通知器-->
<bean id="myAdvice" class="com.study.proxybeanfactory.MyBeforeAdvice"/>

<!---配置bean-->
<bean id="studentService" class="com.study.proxybeanfactory.StudentServiceImpl"/>

<!--配置代理-->
<bean id="studentServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<!--代理的接口-->
<value>com.study.proxybeanfactory.StudentService</value>
</property>
<!--代理的具体实现-->
<property name="target" ref="studentService"></property>
<!--配置拦截器,配置定义的通知器-->
<property name="interceptorNames">
<list>
<value>myAdvice</value>
</list>
</property>
</bean>

</beans>

5.单元测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyBeforeAdviceTest {


@Test
public void testXMLConfig() {
//创建容器,加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/spring/spring-aop.xml");
//从容器中获取bean,注意这里,获取的是StduentService的代理,而不是studentServcie
StudentService studentService = (StudentService) applicationContext.getBean("studentServiceProxy");
//执行save方法,实际上是由代理完成的
studentService.save();
}
}

运行结果:

1
2
准备调用方法:save
执行save方法保存数据

可以看到在save方法执行之前,首先执行了自定义通知器中的before方法。

参考:

Spring AOP 使用介绍,从前世到今生


ProxyFactoryBean生成AopProxy代理对象

1.ProxyFactoryBean

从上面例子看到,配置代理的时候使用的是ProxyFactoryBean,那么就从ProxyFactoryBean开始,看一下AOP的实现原理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
public class ProxyFactoryBean extends ProxyCreatorSupport
implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware {
@Override
@Nullable
public Object getObject() throws BeansException {
//初始化通知器链
initializeAdvisorChain();
//如果是单例模式的bean
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}

/**
* 初始化通知器链
*/
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
if (this.advisorChainInitialized) {
return;
}
//如果拦截器不为空
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
}

// Globals can't be last unless we specified a targetSource using the property...
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
throw new AopConfigException("Target required after globals");
}

// 遍历拦截器
for (String name : this.interceptorNames) {
if (logger.isTraceEnabled()) {
logger.trace("Configuring advisor or advice '" + name + "'");
}
//如果是全局的拦截器
if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
//添加到全局拦截器
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}

else {
// 判断bean是singleton还是prototype
if (this.singleton || this.beanFactory.isSingleton(name)) {
// 根据bean的名字获取通知器
advice = this.beanFactory.getBean(name);
}
else {
// prototype类型的通知器
advice = new PrototypePlaceholderAdvisor(name);
}
addAdvisorOnChainCreation(advice, name);
}
}
}
//初始化过之后设为true
this.advisorChainInitialized = true;
}

}

(1)ProxyFactoryBean中的getObject方法,首先对通知器链进行初始化,通知器链封装了一系列的拦截器,这些拦截器从XML配置文件中读取,为代理对象的生成做好准备。
配置文件中的拦截器interceptorNames:

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
<!--配置代理-->
<bean id="studentServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<!--代理的接口-->
<value>com.study.proxybeanfactory.StudentService</value>
</property>
<!--代理的具体实现-->
<property name="target" ref="studentService"></property>
<!--配置拦截器,配置定义的通知器-->
<property name="interceptorNames">
<list>
<value>myAdvice</value>
</list>
</property>
</bean>

```

(2)advisor通知器的获取是通过IoC容器的getBean(name)方法完成的。
(3)在初始化拦截器链initializeAdvisorChain方法中,需要对bean是prototype还是singleton进行判断,如果是singleton直接根据bean的名字通过容器的getBean方法获取即可,如果是prototype,创建PrototypePlaceholderAdvisor。


回到getObject方法,看一下生成singleton的代理对象的过程,生成singlton代理对象的方法在getSingletonInstance()方法中完成:

``` java
private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
this.targetSource = freshTargetSource();
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
//设置代理对象的接口
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
super.setFrozen(this.freezeProxy);
//生成代理
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}

/**
* 创建AOP代理
*/
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}

/**
* 通过创建的AopProxy获取代理
*/
protected Object getProxy(AopProxy aopProxy) {
return aopProxy.getProxy(this.proxyClassLoader);
}

(1)在createAopProxy()方法创建了AOP代理,方法的返回类型是AopProxy,它是一个接口,它有两个子类CglibAopProxy和JdkDynamicAopProxy,从名字上就可以看出来CglibAopProxy是通过CGLIB来生成代理对象,JdkDynamicAopProxy使用JDK动态代理生成代理对象。

1
2
3
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {}

class CglibAopProxy implements AopProxy, Serializable {}

(2)createAopProxy()方法是在ProxyCreatorSupport中完成的。

2.ProxyCreatorSupport

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class ProxyCreatorSupport extends AdvisedSupport {

private AopProxyFactory aopProxyFactory;

/**
* 构造函数
*/
public ProxyCreatorSupport() {
//这里可以看到代理工厂使用的是DefaultAopProxyFactory
this.aopProxyFactory = new DefaultAopProxyFactory();
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
//使用DefaultAopProxyFactory实现
return getAopProxyFactory().createAopProxy(this);
}

/**
* 获取AopProxyFactory
*/
public AopProxyFactory getAopProxyFactory() {
return this.aopProxyFactory;
}

在createAopProxy方法中,通过获取Aop代理工厂AopProxyFactory创建Aop代理对象,AopProxyFactory是一个接口,ProxyCreatorSupport的构造函数中可以看到,工厂使用DefaultAopProxyFactory实现。

1
2
3
4
5
6
7
8
public interface AopProxyFactory {

/**
* 根据配置信息创建AOP代理
*/
AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;

}

3.Aop代理工厂DefaultAopProxyFactory

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
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//从config中读取信息判断使用哪种方式生成代理
//如果使用显示优化或者配置了目标类
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
//获取目标对象
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
//如果目标对象是接口
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
//使用JDK动态代理
return new JdkDynamicAopProxy(config);
}
//CGLIB生成代理
return new ObjenesisCglibAopProxy(config);
}
else {
//JDK动态代理
return new JdkDynamicAopProxy(config);
}
}

/**
* Determine whether the supplied {@link AdvisedSupport} has only the
* {@link org.springframework.aop.SpringProxy} interface specified
* (or no proxy interfaces specified at all).
*/
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}

}

生成代理对象的过程中,需要从AdvisedSupport对象中获取配置的目标对象,对目标对象配置的检查完成后,根据配置的情况决定使用什么方式创建AopProxy代理对象。如果目标对象是接口类的实现,使用JDK动态代理,否则使用CGLIB生成。

JDK生成Aop代理对象

JdkDynamicAopProxy本身实现了InvocationHandler接口,所以使用Proxy.newProxyInstance方法生成对象时可以将自身指派给代理对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//使用JDK动态代理生成代理对象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

}

CGLIB生成Aop代理对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
class CglibAopProxy implements AopProxy, Serializable {
@Override
public Object getProxy() {
return getProxy(null);
}

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
}

try {
//获取在IoC容器中配置的target对象
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}

// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);

// 创建并配置CGLIB的Enhancer
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
//设置Enhancer对象,包括设置代理接口、回调方法
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);

// 生成代理对象
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
this.advised.getTargetClass() + "]: " +
"Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}

}

到这里,AopProxy对象已经生成了,通过ProxyFactoryBean的getObject方法获取到的对象就不是一个普通的Java对象了,而是一个AopProxy代理对象,当调用目标对象的方法时,会被AopProxy代理对象拦截,对于JDK动态代理,使用的是InvocationHandler的invoke回调入口;对于Cglib,使用的是设置好的callback回调。

参考:

spring技术内幕:深入解析spring架构与设计原理

【Spring源码–AOP的实现】(一)AopProxy代理对象的创建

Spring版本:5.0.5

Bean的生命周期

Posted on 2018-06-10

回想IoC容器的依赖注入过程,有一步是调用AbstractAutowireCapableBeanFactory的doCreateBean方法来创建bean实例,在调用createBeanInstance创建bean的实例以及调用populateBean完成依赖注入之后,调用了initializeBean对bean进行初始化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {

/**
* 创建指定的bean对象
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {

// BeanWrapper用来持有创建出来的Bean对象
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
//如果是单例模式,清除缓存中同名的bean
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//调用createBeanInstance方法完成bean的实例化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}

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

// 判断bean是否是单例模式、允许循环引用和给定的bean是否处于创建状态
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//将创建的baen放入SingletonFactory
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

// 初始化bean的实例
Object exposedObject = bean;
try {
//依赖注入发生的地方
populateBean(beanName, mbd, instanceWrapper);
//初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}

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

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

return exposedObject;
}

/**
* 初始化给定的Bean实例
*/
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
//调用一系列的aware接口实现
invokeAwareMethods(beanName, bean);
}

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//在初始化之前调用BeanPostProcessors后置处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
//处理bean的init方法
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()) {
//初始化之后调用BeanPostProcessors后置处理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

return wrappedBean;
}

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {

Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//bean初始化之后的后置处理器调用
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {

Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//bean初始化之前的后置处理器调用
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}

//把相关的BeanName、BeanClassLoader以及BeanFactory注入到Bean中
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
//设置bean的name
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
//设置bean的类加载器
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
//设置baenFactory到bean中
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}


/**
* 检查bean是否实现了InitializingBean的init方法或者有自定义的init方法
*/
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//如果是InitializingBean的实例
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//启动afterPropertiesSet
((InitializingBean) bean).afterPropertiesSet();
}
}

if (mbd != null && bean.getClass() != NullBean.class) {
//判断Bean是否配置有initMethod
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}

/**
* 获取Bean定义的init-method,然后通过JDK的反射机制得到Method对象,调用在Bean定义中声明的初始化方法。
*/
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
//获取Bean定义的initMethod
String initMethodName = mbd.getInitMethodName();
Assert.state(initMethodName != null, "No init method set");
final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
BeanUtils.findMethod(bean.getClass(), initMethodName) :
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));

if (initMethod == null) {
if (mbd.isEnforceInitMethod()) {
throw new BeanDefinitionValidationException("Couldn't find an init method named '" +
initMethodName + "' on bean with name '" + beanName + "'");
}
else {
if (logger.isDebugEnabled()) {
logger.debug("No default init method named '" + initMethodName +
"' found on bean with name '" + beanName + "'");
}
// Ignore non-existent default lifecycle methods.
return;
}
}

if (logger.isDebugEnabled()) {
logger.debug("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
}

if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(initMethod);
return null;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
initMethod.invoke(bean), getAccessControlContext());
}
catch (PrivilegedActionException pae) {
InvocationTargetException ex = (InvocationTargetException) pae.getException();
throw ex.getTargetException();
}
}
else {
try {
//通过JDK的反射机制调用在Bean定义中声明的初始化方法。
ReflectionUtils.makeAccessible(initMethod);
initMethod.invoke(bean);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}

//容器关闭时销毁bean
@Override
public void destroyBean(Object existingBean) {
new DisposableBeanAdapter(existingBean, getBeanPostProcessors(), getAccessControlContext()).destroy();
}

}

从AbstractAutowireCapableBeanFactory的initializeBean方法看一下Bean的生命周期:

(1)因为initializeBean是在创建bean实例和依赖注入完成之后调用的,所以生命周期的第一步是容器完成Bean的实例化。

(2)在initializeBean方法中首先调用了invokeAwareMethods方法,调用一系列的aware接口实现,把相关的BeanName、BeanClassLoader以及BeanFactory注入到了Bean中。

  • 如果Bean实现了BeanNameAware接口,会调用它的setBeanName方法.

  • 如果Bean实现了BeanFactoryAware接口,会调用它实现的setBeanFactory().

  • 如果这个Bean实现了ApplicationContextAware接口,会调用setApplicationContext方法.

(3)在bean初始化之前调用BeanPostProcessors后置处理器的postProcessBeforeInitialization方法。

(4)调用后置处理器之后,调用了invokeInitMethods方法,这个方法是用来检查
在这个方法中,首先会检查Bean是否实现了InitializingBean接口,如果实现了该接口将会调用afterPropertiesSet方法。如果未实现InitializingBean接口,会检查Bean是否配置有init-method,如果有就调用bean的init-method方法。

1
2
<bean id="student" init-method="initMethod" >
</bean>

(5)invokeInitMethods方法执行完毕后调用BeanPostProcessors后置处理器postProcessAfterInitialization方法。

(6)应用通过IoC容器使用Bean.

(7)当容器关闭时,调用Bean的销毁方法,销毁bean的方法在DisposableBeanAdapter中实现。

  • 如果Bean实现了DisposableBean接口,会调用其实现的destroy方法.
  • 如果配置文件中配置了该bean的destroy-method属性,会自动调用其配置的销毁方法.
1
<bean id="xxx"  destroy-method="destroyMethod">

DisposableBeanAdapter

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
class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {

@Override
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}

if (this.invokeDisposableBean) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
//如果Bean实现了DisposableBean接口,会调用其实现的destroy方法
((DisposableBean) bean).destroy();
return null;
}, acc);
}
else {
((DisposableBean) bean).destroy();
}
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
}
}
}

if (this.destroyMethod != null) {
//调用Spring配置中的destroy-method销毁方法
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToCall = determineDestroyMethod(this.destroyMethodName);
if (methodToCall != null) {
invokeCustomDestroyMethod(methodToCall);
}
}
}
}

参考:

spring技术内幕:深入解析spring架构与设计原理

低调的小黑:Spring Bean的生命周期

IoC容器的依赖注入

Posted on 2018-06-09

spring容器默认在启动时就对bean进行实例化,但是可以修改baen的lazy-init属性为true延迟bean的初始化,使用bean时才实例化:

(1)spring中bean的scope默认是singleton,lazy-init为false,容器启动时实例化bean,修改lazy-init为true时,使用bean时实例化。

1
2
<bean lazy-init="true"/>   
<beans default-lazy-init="true"></beans>

(2)scope是prototype时,lazy-init不管是true还是false都会在使用的时候才对bean实例化。

参考:

林兴洋的博客:spring中的bean何时被实例化

绝地反击T:Spring的IOC、Spring对象初始化bean时机、Spring容器生命周期


从容器中获取bean的过程如下:

1
2
3
4
//使用FileSystemXmlApplicationContext加载配置文件
ApplicationContext context=new FileSystemXmlApplicationContext("classpath*:/spring/applicationContext.xml");
//从容器中获取bean
Student student= (Stuedent) context.getBean("student");//根据id从配置文件中获取bean

依赖注入的发生是在容器中的BeanDefinition数据已经建立好的前提下进行的,这个getBean方法就是触发依赖注入发生的地方,该方法在BeanFactory中有定义,DefaultListableBeanFactory的基类AbstractBeanFactory对该方法有实现,因此就从AbstractBeanFactory的getBean方法入手,看一下IoC容器依赖注入的过程。

1.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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {


//---------------------------------------------------------------------
// BeanFactory接口的实现类
// 这些getBean接口方法最终是通过调用doGetBean来实现的 e
//---------------------------------------------------------------------

@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}

@Override
public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}

@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, null, args, false);
}

public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
throws BeansException {

return doGetBean(name, requiredType, args, false);
}

/**
* 实际取得Bean的地方,也就是触发依赖注入发生的地方
*
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

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

// 根据name从缓存中获取实例,这里获取的是单例模式的bean
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {//如果获取不为空
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else {//如果从缓存中获取失败
// 检查是否已经创建
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

/* 检查BeanDefinition是否存在 */

//获取双亲BeanFactory
BeanFactory parentBeanFactory = getParentBeanFactory();
//如果双亲BeanFactory不为空,并且当前的双亲BeanFacotry不包含该bean
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
//沿着双亲链往上查找
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// 调用双亲带args的getBean方法
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// 调用双亲不带args的getBean方法
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}

if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
//如果双亲容器不包含该bean
try {
//根据Bean的名字取得BeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

//获取当前Bean依赖的所有Bean,这样会触发getBean的递归调用,直到取到一个没有任何依赖的Bean为止
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}

//创建bean的实例
if (mbd.isSingleton()) {//单例模式
sharedInstance = getSingleton(beanName, () -> {
try {
//创建bean的实例
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

else if (mbd.isPrototype()) {//原型模式
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}

// 对创建的Bean进行类型检查,检查类型是否与实例化的bean一致
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}

}

(1)在doGetBean方法中,首先会从缓存中查找bean,如果未找到,则对IoC容器中BeanDefinition是否存在进行检查。检查时会从双亲BeanFactory中查找,如果当前双亲BeanFactory中找不到就顺着双亲BeanFactory链一直向上查找,如果没有双亲BeanFactory,就从当前BeanFactory中取。
(2)获取到bean的BeanDefinition后,会调用ObjectFactory的createBean方法对Bean进行实例化。
(3)实例化之后,会对创建的Bean进行类型检查,检查类型是否与实例化的bean一致,如果正确就返回这个新创建的bean。

2.AbstractAutowireCapableBeanFactory

AbstractAutowireCapableBeanFactory中实现了createBean方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {

//---------------------------------------------------------------------
// Implementation of relevant AbstractBeanFactory template methods
//---------------------------------------------------------------------

/**
* AbstractAutowireCapableBeanFactory的核心方法: 创建bean的实例
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {

if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
//bean的BeanDefinition对象
RootBeanDefinition mbdToUse = mbd;

//判断需要创建的bean是否可以实例化
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}

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

try {
//处理bean的后置处理器,返回的是一个proxy代理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}

try {
//创建bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}

/**
* 创建指定的bean对象
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {

// BeanWrapper用来持有创建出来的Bean对象
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
//如果是单例模式,清除缓存中同名的bean
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//调用createBeanInstance方法完成bean的实例化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}

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

// 判断bean是否是单例模式、允许循环引用和给定的bean是否处于创建状态
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//将创建的baen放入SingletonFactory
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

// 初始化bean的实例
Object exposedObject = bean;
try {
//依赖注入发生的地方
populateBean(beanName, mbd, instanceWrapper);
//初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}

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

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

return exposedObject;
}

/**
* 通过指定的bean name创建一个新的实例,实例化的方法有:工厂方法,构造器注入或者简单的实例化
* @see #instantiateBean
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 确保创建bean可以实例化
Class<?> beanClass = resolveBeanClass(mbd, beanName);

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

Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//如果工厂方法不为空
if (mbd.getFactoryMethodName() != null) {
//使用工厂方法对bean实例化
return instantiateUsingFactoryMethod(beanName, mbd, args);
}

// 创建相同的bean时的一个快捷方式
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}

// 检测构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//使用带参构造函数对bean实例化
return autowireConstructor(beanName, mbd, ctors, args);
}

//使用无参的构造函数实例化bean
return instantiateBean(beanName, mbd);
}

/**
* 使用默认的构造函数实例化bean,默认使用CGLIB实例化bean
*/
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
//getInstantiationStrategy()返回的是CGLIB策略
getInstantiationStrategy().instantiate(mbd, beanName, parent),//CGLIB对bean进行实例化
getAccessControlContext());
}
else {
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}

protected InstantiationStrategy getInstantiationStrategy() {
return this.instantiationStrategy;
}
//CLIGB
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();

}

doCreateBean中两个方法:

(1)createBeanInstance方法:

在这个方法中,又会调用instantiateBean和autowireConstructor创建bean的实例。

autowireConstructor中是通过ConstructorResolver的autowireConstructor方法完成bean的实例化的。

instantiateBean中,调用getInstantiationStrategy()返回了CglibSubclassingInstantiationStrategy对象,调用该对象的instantiate方法对bean实例化,从名字上就可以看出是通过CGLIB实例化的。CglibSubclassingInstantiationStrategy是SimpleInstantiationStrategy的子类,实际上先走的SimpleInstantiationStrategy的instantiate方法,在该方法中调用CglibSubclassingInstantiationStrategy的instantiateWithMethodInjection方法完成的。

SimpleInstantiationStrategy
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
public class SimpleInstantiationStrategy implements InstantiationStrategy {

private static final ThreadLocal<Method> currentlyInvokedFactoryMethod = new ThreadLocal<>();

@Nullable
public static Method getCurrentlyInvokedFactoryMethod() {
return currentlyInvokedFactoryMethod.get();
}


@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
//取得指定的构造器或者生成对象的工厂方法对Bean进行实例化
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
//获取bean的class
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
//调用BeanUtils的instantiateClass方法通过构造器对bean进行实例化
return BeanUtils.instantiateClass(constructorToUse);
}
else {
//CglibSubclassingInstantiationStrategy中对该方法有实现
return instantiateWithMethodInjection(bd, beanName, owner);
}
}

protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName,
BeanFactory owner, @Nullable Constructor<?> ctor, @Nullable Object... args) {

throw new UnsupportedOperationException("Method Injection not supported in SimpleInstantiationStrategy");
}

SimpleInstantiationStrategy的instantiateWithMethodInjection只抛出了一个异常,其他的什么也没做。CglibSubclassingInstantiationStrategy对该方法进行了重写。

CglibSubclassingInstantiationStrategy
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
public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy {
@Override
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// 调用instantiate完成bean的实例化
return instantiateWithMethodInjection(bd, beanName, owner, null);
}

@Override
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Constructor<?> ctor, @Nullable Object... args) {

// 调用instantiate完成bean的实例化
return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
}


/**
* An inner class created for historical reasons to avoid external CGLIB dependency
* in Spring versions earlier than 3.2.
*/
private static class CglibSubclassCreator {

private static final Class<?>[] CALLBACK_TYPES = new Class<?>[]
{NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class};

private final RootBeanDefinition beanDefinition;

private final BeanFactory owner;

CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) {
this.beanDefinition = beanDefinition;
this.owner = owner;
}

/**
* 创建实例的地方
*/
public Object instantiate(@Nullable Constructor<?> ctor, @Nullable Object... args) {
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
Object instance;
if (ctor == null) {
instance = BeanUtils.instantiateClass(subclass);
}
else {
try {
Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
instance = enhancedSubclassConstructor.newInstance(args);
}
catch (Exception ex) {
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
"Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
}
}
// SPR-10785: set callbacks directly on the instance instead of in the
// enhanced class (via the Enhancer) in order to avoid memory leaks.
Factory factory = (Factory) instance;
factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
return instance;
}

/**
* 根据提供的bean使用CGLIB创建一个增强的子类
*/
private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanDefinition.getBeanClass());
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
if (this.owner instanceof ConfigurableBeanFactory) {
ClassLoader cl = ((ConfigurableBeanFactory) this.owner).getBeanClassLoader();
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));
}
enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
enhancer.setCallbackTypes(CALLBACK_TYPES);
return enhancer.createClass();
}
}
}

CglibSubclassingInstantiationStrategy的instantiateWithMethodInjection方法中调用了CglibSubclassCreator的instantiate方法完成了bean的实例化。

(2)populateBean方法

该方法的作用是设置bean之间的依赖关系,完成整个依赖注入的过程。

回到AbstractAutowireCapableBeanFactory的populateBean方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
   /**
* Populate the bean instance in the given BeanWrapper with the property values
* from the bean definition.
* @param beanName bean的name
* @param mbd bean的BeanDefinition
* @param bw bean的实例
*/
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {//如果bean的实例为空
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}


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;
}
//获取BeanDefinition中的property值
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
//如果是byName或者byType注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

// 根据bean的名字注入
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;
}

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

if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
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);
}
}

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

/**
* 具体的对属性进行解析然后注入的过程
*/
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs.isEmpty()) {//如果PropertyValues为空
return;
}

if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}

MutablePropertyValues mpvs = null;
List<PropertyValue> original;

if (pvs instanceof MutablePropertyValues) {//如果是MutablePropertyValues
mpvs = (MutablePropertyValues) pvs;
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
try {
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
}

TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

// Create a deep copy, resolving any references for values.
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
String propertyName = pv.getName();
Object originalValue = pv.getValue();
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
}


try {
// 设置属性值,依赖注入发生的地方,会在BeanWrapperImpl中完成
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}

BeanWrapper是一个接口,setPropertyValues方法是在 AbstractNestablePropertyAccessor中实现的,BeanWrapperImpl又是AbstractNestablePropertyAccessor的子类,因此可以通过BeanWrapperImpl调用setPropertyValues方法完成属性值的设置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyAccessor {

/*
* 设置property value
*/
@Override
public void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException {
AbstractNestablePropertyAccessor nestedPa;
try {
nestedPa = getPropertyAccessorForPropertyPath(propertyName);
}
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
"Nested property in path '" + propertyName + "' does not exist", ex);
}
PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));
nestedPa.setPropertyValue(tokens, new PropertyValue(propertyName, value));
}

/*
* 设置property value
*/
@Override
public void setPropertyValue(PropertyValue pv) throws BeansException {
PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;
if (tokens == null) {
String propertyName = pv.getName();
AbstractNestablePropertyAccessor nestedPa;
try {
nestedPa = getPropertyAccessorForPropertyPath(propertyName);
}
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
"Nested property in path '" + propertyName + "' does not exist", ex);
}
tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));
if (nestedPa == this) {
pv.getOriginalPropertyValue().resolvedTokens = tokens;
}
nestedPa.setPropertyValue(tokens, pv);
}
else {
setPropertyValue(tokens, pv);
}
}

protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
if (tokens.keys != null) {
processKeyedProperty(tokens, pv);
}
else {
processLocalProperty(tokens, pv);
}
}

private void processKeyedProperty(PropertyTokenHolder tokens, PropertyValue pv) {
Object propValue = getPropertyHoldingValue(tokens);
PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
if (ph == null) {
throw new InvalidPropertyException(
getRootClass(), this.nestedPath + tokens.actualName, "No property handler found");
}
Assert.state(tokens.keys != null, "No token keys");
String lastKey = tokens.keys[tokens.keys.length - 1];

if (propValue.getClass().isArray()) {//如果属性是Array类型
Class<?> requiredType = propValue.getClass().getComponentType();
int arrayIndex = Integer.parseInt(lastKey);
Object oldValue = null;
try {
if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
oldValue = Array.get(propValue, arrayIndex);
}
Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
requiredType, ph.nested(tokens.keys.length));
int length = Array.getLength(propValue);
if (arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {
Class<?> componentType = propValue.getClass().getComponentType();
Object newArray = Array.newInstance(componentType, arrayIndex + 1);
System.arraycopy(propValue, 0, newArray, 0, length);
setPropertyValue(tokens.actualName, newArray);
propValue = getPropertyValue(tokens.actualName);
}
Array.set(propValue, arrayIndex, convertedValue);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
"Invalid array index in property path '" + tokens.canonicalName + "'", ex);
}
}

else if (propValue instanceof List) {//如果bean的属性是list类型
Class<?> requiredType = ph.getCollectionType(tokens.keys.length);
List<Object> list = (List<Object>) propValue;
int index = Integer.parseInt(lastKey);
Object oldValue = null;
if (isExtractOldValueForEditor() && index < list.size()) {
oldValue = list.get(index);
}
Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
requiredType, ph.nested(tokens.keys.length));
int size = list.size();
if (index >= size && index < this.autoGrowCollectionLimit) {
for (int i = size; i < index; i++) {
try {
list.add(null);
}
catch (NullPointerException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
"Cannot set element with index " + index + " in List of size " +
size + ", accessed using property path '" + tokens.canonicalName +
"': List does not support filling up gaps with null elements");
}
}
list.add(convertedValue);
}
else {
try {
list.set(index, convertedValue);
}
catch (IndexOutOfBoundsException ex) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
"Invalid list index in property path '" + tokens.canonicalName + "'", ex);
}
}
}

else if (propValue instanceof Map) {//如果属性是map类型
Class<?> mapKeyType = ph.getMapKeyType(tokens.keys.length);
Class<?> mapValueType = ph.getMapValueType(tokens.keys.length);
Map<Object, Object> map = (Map<Object, Object>) propValue;
// IMPORTANT: Do not pass full property name in here - property editors
// must not kick in for map keys but rather only for map values.
TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(mapKeyType);
Object convertedMapKey = convertIfNecessary(null, null, lastKey, mapKeyType, typeDescriptor);
Object oldValue = null;
if (isExtractOldValueForEditor()) {
oldValue = map.get(convertedMapKey);
}
// Pass full property name and old value in here, since we want full
// conversion ability for map values.
Object convertedMapValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
mapValueType, ph.nested(tokens.keys.length));
map.put(convertedMapKey, convertedMapValue);
}

else {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
"Property referenced in indexed property path '" + tokens.canonicalName +
"' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
}
}

}

在Bean的创建和对象依赖注入的过程中,需要依据BeanDefinition中的信息递归的完成依赖注入,这些递归都是以getBean为入口的。一个递归是在上下文体系中查找需要的Bean和创建Bean的递归调用,另一个递归是在依赖注入时,通过递归调用容器的getBean方法,得到当前Bean的依赖,同时也触发对依赖Bean的创建和注入。对Bean的属性进行依赖注入时,解析的过程也是一个递归的过程。这样,根据依赖关系,一层一层的完成Bean的创建和注入,直到最后完成当然Bean的创建。

在Bean创建和依赖注入完成以后,在IoC容器中建立起一系列依靠依赖关系联系起来的Bean。

来自:spring技术内幕:深入解析spring架构与设计原理

Spring版本:5.0.5

IoC容器初始化过程(二):BeanDefinition载入和注册

Posted on 2018-06-05

BeanDefinition的载入

在IoC容器初始化过程(1)-Resource定位中知道,调用AbstractBeanDefinitionReader中的loadBeanDefinitions方法时不管传入的参数是String类型还是Resource类型,最终都是由XmlBeanDefinitionReader中的loadBeanDefinitions方法实现的,那么就从XmlBeanDefinitionReader开始,看一下载入BeanDefinition的过程。

1.XmlBeanDefinitionReader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {

@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
//载入XML形式的资源文件,并使用Resource对象创建EncodedResource对象
return loadBeanDefinitions(new EncodedResource(resource));
}

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
//获取资源对象集合
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
//将当前的资源对象添加到EncodedResource
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
//从EncodedResource获取资源对象的输入流,得到XML文件
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
//创建InputSource准备进行读取
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
//设置编码
inputSource.setEncoding(encodedResource.getEncoding());
}
//进行BeanDefinition的载入
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
//移除已经读取过的资源对象
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}

public int loadBeanDefinitions(InputSource inputSource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(inputSource, "resource loaded through SAX InputSource");
}

public int loadBeanDefinitions(InputSource inputSource, @Nullable String resourceDescription)
throws BeanDefinitionStoreException {

return doLoadBeanDefinitions(inputSource, new DescriptiveResource(resourceDescription));
}

/**
* 从XML文件具体载入BeanDefinition的方法
* @param inputSource the SAX InputSource to read from
* @param resource the resource descriptor for the XML file
*/
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//取得XML文件的Document对象
Document doc = doLoadDocument(inputSource, resource);
//注册BeanDefinition
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
}
catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid", ex);
}
catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}

/**
* 向容器中注册BeanDefinition
* 按照Spring的Bean语义要求进行解析资源文件并转换为内部的数据结构BeanDefinition
*/
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//创建BeanDefinitionDocumentReader用来解析Document,也就是解析XML配置文件
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//具体的解析过程在registerBeanDefinitions方法中完成,该方法在DefaultBeanDefinitionDocumentReader中有实现
int countBefore = getRegistry().getBeanDefinitionCount();
//注册BeanDefinition
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
//对载入Bean的数量进行统计
return getRegistry().getBeanDefinitionCount() - countBefore;
}

/**
* 创建BeanDefinitionDocumentReader
* 作用是从XML文件中读取bean信息转为BeanDefinition
*/
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
}

protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
//资源文件转为Document对象
return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
getValidationModeForResource(resource), isNamespaceAware());
}

}
  • BeanDefinition载入时首先通过DocumentLoader将资源文件转为Document对象,然后使用BeanDefinitionDocumentReader进行解析。
  • BeanDefinitionDocumentReader是一个接口,具体由DefaultBeanDefinitionDocumentReader实现BeanDefinition的注册。

2.DefaultBeanDefinitionDocumentReader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {

/**
* 注册BeanDefinition
*/
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
//获取根节点
Element root = doc.getDocumentElement();
//注册每一个BeanDefinition
doRegisterBeanDefinitions(root);
}

/**
* 根据根节点注册每一个BeanDefinition
*/
protected void doRegisterBeanDefinitions(Element root) {
// 用于解析BeanDefinition的委托类
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);

if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
//在开始处理bean定义之前,允许XML通过处理任何自定义元素类型进行扩展
preProcessXml(root);
//从根元素开始解析
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);

this.delegate = parent;
}
/**
* 从根元素开始解析BeanDefinition
*/
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
//获取根节点的所有子节点
NodeList nl = root.getChildNodes();
//遍历根节点的子节点集合
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
//如果是默认的元素
if (delegate.isDefaultNamespace(ele)) {
//解析默认元素
parseDefaultElement(ele, delegate);
}
else {
//解析自定义元素
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}

/**
* 解析默认的元素(import、alias、bean、beans)
*/
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//解析import
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {//alias
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {//bean
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}

/**
* 处理给定的Element元素,解析BeanDefinition并注册
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 向IoC容器注册解析得到的BeanDefnition
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// 注册完成后,发送消息
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
}
  • processBeanDefinition()方法中,使用BeanDefinitionParserDelegate对Element进行解析,返回的是BeanDefinitionHolder对象,用它来完成向IoC容器的注册 。BeanDefinitionHolder是BeanDefinition的封装类,除了BeanDefinition还持有其他与BeanDefinition的使用相关的信息,比如Bean的名字、别名集合等。
  • BeanDefinition生成后,调用了BeanDefinitionReaderUtils的registerBeanDefinition()完成BeanDefinition的注册(注册BeanDefinition的过程会从该方法入手)。

BeanDefinitionHolder

1
2
3
4
5
6
7
8
9
public class BeanDefinitionHolder implements BeanMetadataElement {

private final BeanDefinition beanDefinition;

private final String beanName;

@Nullable
private final String[] aliases;
}

3.BeanDefinitionParserDelegate

BeanDefinitionParserDelegate是具体解析XML中的元素与生成BeanDefinition的地方。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
public class BeanDefinitionParserDelegate {
/**
* 解析XML元素
*/
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}

/**
* 解析元素的详细过程,并返回BeanDefinitionHolder对象
*/
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
//获取<bean>元素中定义的属性值
String id = ele.getAttribute(ID_ATTRIBUTE);//获取ID属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);//获取name属性
//别名
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}

String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}

if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
//对Bean元素的详细解析,生成BeanDefinition
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
//对BeanDefinition封装返回BeanDefinitionHolder
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}

return null;
}

/**
* 解析元素生成BeanDefinition
*/
@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {

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

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

try {
// 创建BeanDefinition
AbstractBeanDefinition bd = createBeanDefinition(className, parent);

parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);//解析attributes元素
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

parseMetaElements(ele, bd);//解析meta元素
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

parseConstructorArgElements(ele, bd);
parsePropertyElements(ele, bd);//解析Property元素
parseQualifierElements(ele, bd);

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

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

return null;
}
}

在parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean)中生成了BeanDefinition对象。然后进行了一系列的解析XML元素的方法,设置到BeanDefinition中,最后将创建的BeanDefinition返回,完成BeanDefinition的载入。

BeanDefinition的注册

BeanDefinition的载入过程中,在DefaultBeanDefinitionDocumentReader中创建BeanDefinition后调用了BeanDefinitionReaderUtils对BeanDefiniton进行注册。

1.BeanDefinitionReaderUtils

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class BeanDefinitionReaderUtils {
/**
* 注册BeanDefinition
*/
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {

// 获取bean的name
String beanName = definitionHolder.getBeanName();
//注册BeanDefinition
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

// 注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
}

BeanDefinitionRegistry是一个接口,registerBeanDefinition方法由它的子类DefaultListableBeanFactory实现。

2.DefaultListableBeanFactory

在DefaultListableBeanFactory可以看到有一个beanDefinitionMap成员变量,每一个BeanDefinition都会注册到该集合中,IoC容器通过这个HashMap来持有这些BeanDefinition数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

/** 存放BeanDefinition对象的Map集合,key为bean的name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

//---------------------------------------------------------------------
// 注册BeanDefinition
//---------------------------------------------------------------------

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {

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

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

BeanDefinition oldBeanDefinition;
//检查是不是有相同名字的BeanDefinition已经在IoC容器中注册了,如果有相同的BeanDefinition,但又不允许覆盖,会抛出异常
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {//是否已经启动注册
// 使用synchronized保持数据的一致性
synchronized (this.beanDefinitionMap) {
//注册BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
//注册BeanDefinition,将解析后BeanDefinition放入map,key为bean name,value为BeanDefinition对象
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}

if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
}

参考:

spring技术内幕:深入解析spring架构与设计原理

Spring版本:5.0.5

1…456

shan

53 posts
12 tags
© 2022 shan
Powered by Hexo
|
Theme — NexT.Muse v5.1.4