Skip to content

Commit fba61d2

Browse files
committed
Refactoring : Parse pending elements in Configuration
1 parent ac9d836 commit fba61d2

File tree

3 files changed

+109
-108
lines changed

3 files changed

+109
-108
lines changed

src/main/java/org/apache/ibatis/builder/annotation/MapperAnnotationBuilder.java

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2009-2023 the original author or authors.
2+
* Copyright 2009-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,7 +27,6 @@
2727
import java.util.Arrays;
2828
import java.util.Collection;
2929
import java.util.HashMap;
30-
import java.util.Iterator;
3130
import java.util.List;
3231
import java.util.Map;
3332
import java.util.Optional;
@@ -135,29 +134,14 @@ public void parse() {
135134
}
136135
}
137136
}
138-
parsePendingMethods();
137+
configuration.parsePendingMethods(false);
139138
}
140139

141140
private static boolean canHaveStatement(Method method) {
142141
// issue #237
143142
return !method.isBridge() && !method.isDefault();
144143
}
145144

146-
private void parsePendingMethods() {
147-
Collection<MethodResolver> incompleteMethods = configuration.getIncompleteMethods();
148-
synchronized (incompleteMethods) {
149-
Iterator<MethodResolver> iter = incompleteMethods.iterator();
150-
while (iter.hasNext()) {
151-
try {
152-
iter.next().resolve();
153-
iter.remove();
154-
} catch (IncompleteElementException e) {
155-
// This method is still missing a resource
156-
}
157-
}
158-
}
159-
}
160-
161145
private void loadXmlResource() {
162146
// Spring may not know the real resource name so we check a flag
163147
// to prevent loading again a resource twice

src/main/java/org/apache/ibatis/builder/xml/XMLMapperBuilder.java

Lines changed: 4 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2009-2023 the original author or authors.
2+
* Copyright 2009-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,10 +19,8 @@
1919
import java.io.Reader;
2020
import java.util.ArrayList;
2121
import java.util.Arrays;
22-
import java.util.Collection;
2322
import java.util.Collections;
2423
import java.util.HashMap;
25-
import java.util.Iterator;
2624
import java.util.List;
2725
import java.util.Map;
2826
import java.util.Properties;
@@ -101,9 +99,9 @@ public void parse() {
10199
configuration.addLoadedResource(resource);
102100
bindMapperForNamespace();
103101
}
104-
parsePendingResultMaps();
105-
parsePendingCacheRefs();
106-
parsePendingStatements();
102+
configuration.parsePendingResultMaps(false);
103+
configuration.parsePendingCacheRefs(false);
104+
configuration.parsePendingStatements(false);
107105
}
108106

109107
public XNode getSqlFragment(String refid) {
@@ -147,51 +145,6 @@ private void buildStatementFromContext(List<XNode> list, String requiredDatabase
147145
}
148146
}
149147

150-
private void parsePendingResultMaps() {
151-
Collection<ResultMapResolver> incompleteResultMaps = configuration.getIncompleteResultMaps();
152-
synchronized (incompleteResultMaps) {
153-
Iterator<ResultMapResolver> iter = incompleteResultMaps.iterator();
154-
while (iter.hasNext()) {
155-
try {
156-
iter.next().resolve();
157-
iter.remove();
158-
} catch (IncompleteElementException e) {
159-
// ResultMap is still missing a resource...
160-
}
161-
}
162-
}
163-
}
164-
165-
private void parsePendingCacheRefs() {
166-
Collection<CacheRefResolver> incompleteCacheRefs = configuration.getIncompleteCacheRefs();
167-
synchronized (incompleteCacheRefs) {
168-
Iterator<CacheRefResolver> iter = incompleteCacheRefs.iterator();
169-
while (iter.hasNext()) {
170-
try {
171-
iter.next().resolveCacheRef();
172-
iter.remove();
173-
} catch (IncompleteElementException e) {
174-
// Cache ref is still missing a resource...
175-
}
176-
}
177-
}
178-
}
179-
180-
private void parsePendingStatements() {
181-
Collection<XMLStatementBuilder> incompleteStatements = configuration.getIncompleteStatements();
182-
synchronized (incompleteStatements) {
183-
Iterator<XMLStatementBuilder> iter = incompleteStatements.iterator();
184-
while (iter.hasNext()) {
185-
try {
186-
iter.next().parseStatementNode();
187-
iter.remove();
188-
} catch (IncompleteElementException e) {
189-
// Statement is still missing a resource...
190-
}
191-
}
192-
}
193-
}
194-
195148
private void cacheRefElement(XNode context) {
196149
if (context != null) {
197150
configuration.addCacheRef(builderAssistant.getCurrentNamespace(), context.getStringAttribute("namespace"));

src/main/java/org/apache/ibatis/session/Configuration.java

Lines changed: 103 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2009-2023 the original author or authors.
2+
* Copyright 2009-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
2626
import java.util.Properties;
2727
import java.util.Set;
2828
import java.util.concurrent.ConcurrentHashMap;
29+
import java.util.concurrent.locks.ReentrantLock;
2930
import java.util.function.BiFunction;
3031

3132
import org.apache.ibatis.binding.MapperRegistry;
@@ -95,7 +96,6 @@
9596
import org.apache.ibatis.type.TypeAliasRegistry;
9697
import org.apache.ibatis.type.TypeHandler;
9798
import org.apache.ibatis.type.TypeHandlerRegistry;
98-
import org.apache.ibatis.util.LockKit;
9999

100100
/**
101101
* @author Clinton Begin
@@ -172,6 +172,11 @@ public class Configuration {
172172
protected final Collection<ResultMapResolver> incompleteResultMaps = new LinkedList<>();
173173
protected final Collection<MethodResolver> incompleteMethods = new LinkedList<>();
174174

175+
private final ReentrantLock incompleteResultMapsLock = new ReentrantLock();
176+
private final ReentrantLock incompleteCacheRefsLock = new ReentrantLock();
177+
private final ReentrantLock incompleteStatementsLock = new ReentrantLock();
178+
private final ReentrantLock incompleteMethodsLock = new ReentrantLock();
179+
175180
/*
176181
* A map holds cache-ref relationship. The key is the namespace that references a cache bound to another namespace and
177182
* the value is the namespace which the actual cache is bound to.
@@ -832,34 +837,70 @@ public Collection<MappedStatement> getMappedStatements() {
832837
return mappedStatements.values();
833838
}
834839

840+
/**
841+
* @deprecated call {@link #parsePendingStatements(boolean)}
842+
*/
843+
@Deprecated
835844
public Collection<XMLStatementBuilder> getIncompleteStatements() {
836845
return incompleteStatements;
837846
}
838847

839848
public void addIncompleteStatement(XMLStatementBuilder incompleteStatement) {
840-
incompleteStatements.add(incompleteStatement);
849+
incompleteStatementsLock.lock();
850+
try {
851+
incompleteStatements.add(incompleteStatement);
852+
} finally {
853+
incompleteStatementsLock.unlock();
854+
}
841855
}
842856

857+
/**
858+
* @deprecated call {@link #parsePendingCacheRefs(boolean)}
859+
*/
860+
@Deprecated
843861
public Collection<CacheRefResolver> getIncompleteCacheRefs() {
844862
return incompleteCacheRefs;
845863
}
846864

847865
public void addIncompleteCacheRef(CacheRefResolver incompleteCacheRef) {
848-
incompleteCacheRefs.add(incompleteCacheRef);
866+
incompleteCacheRefsLock.lock();
867+
try {
868+
incompleteCacheRefs.add(incompleteCacheRef);
869+
} finally {
870+
incompleteCacheRefsLock.unlock();
871+
}
849872
}
850873

874+
/**
875+
* @deprecated call {@link #parsePendingResultMaps(boolean)}
876+
*/
877+
@Deprecated
851878
public Collection<ResultMapResolver> getIncompleteResultMaps() {
852879
return incompleteResultMaps;
853880
}
854881

855882
public void addIncompleteResultMap(ResultMapResolver resultMapResolver) {
856-
incompleteResultMaps.add(resultMapResolver);
883+
incompleteResultMapsLock.lock();
884+
try {
885+
incompleteResultMaps.add(resultMapResolver);
886+
} finally {
887+
incompleteResultMapsLock.unlock();
888+
}
857889
}
858890

859891
public void addIncompleteMethod(MethodResolver builder) {
860-
incompleteMethods.add(builder);
892+
incompleteMethodsLock.lock();
893+
try {
894+
incompleteMethods.add(builder);
895+
} finally {
896+
incompleteMethodsLock.unlock();
897+
}
861898
}
862899

900+
/**
901+
* @deprecated call {@link #parsePendingMethods(boolean)}
902+
*/
903+
@Deprecated
863904
public Collection<MethodResolver> getIncompleteMethods() {
864905
return incompleteMethods;
865906
}
@@ -923,48 +964,71 @@ public void addCacheRef(String namespace, String referencedNamespace) {
923964
* are added as it provides fail-fast statement validation.
924965
*/
925966
protected void buildAllStatements() {
926-
parsePendingResultMaps();
927-
if (!incompleteCacheRefs.isEmpty()) {
928-
LockKit.ReentrantLock lock = LockKit.obtainLock(incompleteCacheRefs);
929-
lock.lock();
930-
try {
931-
incompleteCacheRefs.removeIf(x -> x.resolveCacheRef() != null);
932-
} finally {
933-
lock.unlock();
967+
parsePendingResultMaps(true);
968+
parsePendingCacheRefs(true);
969+
parsePendingStatements(true);
970+
parsePendingMethods(true);
971+
}
972+
973+
public void parsePendingMethods(boolean reportUnresolved) {
974+
if (incompleteMethods.isEmpty()) {
975+
return;
976+
}
977+
incompleteMethodsLock.lock();
978+
try {
979+
incompleteMethods.removeIf(x -> {
980+
x.resolve();
981+
return true;
982+
});
983+
} catch (IncompleteElementException e) {
984+
if (reportUnresolved) {
985+
throw e;
934986
}
987+
} finally {
988+
incompleteMethodsLock.unlock();
935989
}
936-
if (!incompleteStatements.isEmpty()) {
937-
LockKit.ReentrantLock lock = LockKit.obtainLock(incompleteStatements);
938-
lock.lock();
939-
try {
940-
incompleteStatements.removeIf(x -> {
941-
x.parseStatementNode();
942-
return true;
943-
});
944-
} finally {
945-
lock.unlock();
990+
}
991+
992+
public void parsePendingStatements(boolean reportUnresolved) {
993+
if (incompleteStatements.isEmpty()) {
994+
return;
995+
}
996+
incompleteStatementsLock.lock();
997+
try {
998+
incompleteStatements.removeIf(x -> {
999+
x.parseStatementNode();
1000+
return true;
1001+
});
1002+
} catch (IncompleteElementException e) {
1003+
if (reportUnresolved) {
1004+
throw e;
9461005
}
1006+
} finally {
1007+
incompleteStatementsLock.unlock();
1008+
}
1009+
}
1010+
1011+
public void parsePendingCacheRefs(boolean reportUnresolved) {
1012+
if (incompleteCacheRefs.isEmpty()) {
1013+
return;
9471014
}
948-
if (!incompleteMethods.isEmpty()) {
949-
LockKit.ReentrantLock lock = LockKit.obtainLock(incompleteMethods);
950-
lock.lock();
951-
try {
952-
incompleteMethods.removeIf(x -> {
953-
x.resolve();
954-
return true;
955-
});
956-
} finally {
957-
lock.unlock();
1015+
incompleteCacheRefsLock.lock();
1016+
try {
1017+
incompleteCacheRefs.removeIf(x -> x.resolveCacheRef() != null);
1018+
} catch (IncompleteElementException e) {
1019+
if (reportUnresolved) {
1020+
throw e;
9581021
}
1022+
} finally {
1023+
incompleteCacheRefsLock.unlock();
9591024
}
9601025
}
9611026

962-
private void parsePendingResultMaps() {
1027+
public void parsePendingResultMaps(boolean reportUnresolved) {
9631028
if (incompleteResultMaps.isEmpty()) {
9641029
return;
9651030
}
966-
LockKit.ReentrantLock lock = LockKit.obtainLock(incompleteResultMaps);
967-
lock.lock();
1031+
incompleteResultMapsLock.lock();
9681032
try {
9691033
boolean resolved;
9701034
IncompleteElementException ex = null;
@@ -981,12 +1045,12 @@ private void parsePendingResultMaps() {
9811045
}
9821046
}
9831047
} while (resolved);
984-
if (!incompleteResultMaps.isEmpty() && ex != null) {
1048+
if (reportUnresolved && !incompleteResultMaps.isEmpty() && ex != null) {
9851049
// At least one result map is unresolvable.
9861050
throw ex;
9871051
}
9881052
} finally {
989-
lock.unlock();
1053+
incompleteResultMapsLock.unlock();
9901054
}
9911055
}
9921056

0 commit comments

Comments
 (0)