Skip to content

Commit eaccb56

Browse files
committed
Merge branch '6.2.x'
# Conflicts: # spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java
2 parents 444573d + 4f63047 commit eaccb56

File tree

7 files changed

+131
-36
lines changed

7 files changed

+131
-36
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1451,11 +1451,18 @@ protected void checkForAliasCircle(String name, String alias) {
14511451
}
14521452
}
14531453

1454+
@Override
1455+
protected void addSingleton(String beanName, Object singletonObject) {
1456+
super.addSingleton(beanName, singletonObject);
1457+
Predicate<Class<?>> filter = (beanType -> beanType != Object.class && beanType.isInstance(singletonObject));
1458+
this.allBeanNamesByType.keySet().removeIf(filter);
1459+
this.singletonBeanNamesByType.keySet().removeIf(filter);
1460+
}
1461+
14541462
@Override
14551463
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
14561464
super.registerSingleton(beanName, singletonObject);
14571465
updateManualSingletonNames(set -> set.add(beanName), set -> !this.beanDefinitionMap.containsKey(beanName));
1458-
clearByTypeCache();
14591466
}
14601467

14611468
@Override

spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3211,6 +3211,29 @@ void nonPublicEnum() {
32113211
assertThat(holder.getNonPublicEnum()).isEqualTo(NonPublicEnum.VALUE_1);
32123212
}
32133213

3214+
@Test
3215+
void mostSpecificCacheEntryForTypeMatching() {
3216+
RootBeanDefinition bd1 = new RootBeanDefinition();
3217+
bd1.setFactoryBeanName("config");
3218+
bd1.setFactoryMethodName("create");
3219+
lbf.registerBeanDefinition("config", new RootBeanDefinition(BeanWithFactoryMethod.class));
3220+
lbf.registerBeanDefinition("bd1", bd1);
3221+
lbf.registerBeanDefinition("bd2", new RootBeanDefinition(NestedTestBean.class));
3222+
lbf.freezeConfiguration();
3223+
3224+
String[] allBeanNames = lbf.getBeanNamesForType(Object.class);
3225+
String[] nestedBeanNames = lbf.getBeanNamesForType(NestedTestBean.class);
3226+
assertThat(lbf.getType("bd1")).isEqualTo(TestBean.class);
3227+
assertThat(lbf.getBeanNamesForType(TestBean.class)).containsExactly("bd1");
3228+
assertThat(lbf.getBeanNamesForType(DerivedTestBean.class)).isEmpty();
3229+
lbf.getBean("bd1");
3230+
assertThat(lbf.getType("bd1")).isEqualTo(DerivedTestBean.class);
3231+
assertThat(lbf.getBeanNamesForType(TestBean.class)).containsExactly("bd1");
3232+
assertThat(lbf.getBeanNamesForType(DerivedTestBean.class)).containsExactly("bd1");
3233+
assertThat(lbf.getBeanNamesForType(NestedTestBean.class)).isSameAs(nestedBeanNames);
3234+
assertThat(lbf.getBeanNamesForType(Object.class)).isSameAs(allBeanNames);
3235+
}
3236+
32143237

32153238
private int registerBeanDefinitions(Properties p) {
32163239
return registerBeanDefinitions(p, null);
@@ -3427,7 +3450,7 @@ public void setName(String name) {
34273450
}
34283451

34293452
public TestBean create() {
3430-
TestBean tb = new TestBean();
3453+
DerivedTestBean tb = new DerivedTestBean();
34313454
tb.setName(this.name);
34323455
return tb;
34333456
}
@@ -3655,11 +3678,11 @@ private static class FactoryBeanDependentBean {
36553678

36563679
private FactoryBean<?> factoryBean;
36573680

3658-
public final FactoryBean<?> getFactoryBean() {
3681+
public FactoryBean<?> getFactoryBean() {
36593682
return this.factoryBean;
36603683
}
36613684

3662-
public final void setFactoryBean(final FactoryBean<?> factoryBean) {
3685+
public void setFactoryBean(FactoryBean<?> factoryBean) {
36633686
this.factoryBean = factoryBean;
36643687
}
36653688
}

spring-core/src/main/java/org/springframework/core/io/AbstractFileResolvingResource.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,12 +361,22 @@ public long lastModified() throws IOException {
361361
* @throws IOException if thrown from URLConnection methods
362362
*/
363363
protected void customizeConnection(URLConnection con) throws IOException {
364-
ResourceUtils.useCachesIfNecessary(con);
364+
useCachesIfNecessary(con);
365365
if (con instanceof HttpURLConnection httpCon) {
366366
customizeConnection(httpCon);
367367
}
368368
}
369369

370+
/**
371+
* Apply {@link URLConnection#setUseCaches useCaches} if necessary.
372+
* @param con the URLConnection to customize
373+
* @since 6.2.10
374+
* @see ResourceUtils#useCachesIfNecessary(URLConnection)
375+
*/
376+
void useCachesIfNecessary(URLConnection con) {
377+
ResourceUtils.useCachesIfNecessary(con);
378+
}
379+
370380
/**
371381
* Customize the given {@link HttpURLConnection} before fetching the resource.
372382
* <p>Can be overridden in subclasses for configuring request headers and timeouts.

spring-core/src/main/java/org/springframework/core/io/FileUrlResource.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ public WritableByteChannel writableChannel() throws IOException {
109109

110110
@Override
111111
public Resource createRelative(String relativePath) throws MalformedURLException {
112-
return new FileUrlResource(createRelativeURL(relativePath));
112+
FileUrlResource resource = new FileUrlResource(createRelativeURL(relativePath));
113+
resource.useCaches = this.useCaches;
114+
return resource;
113115
}
114116

115117
}

spring-core/src/main/java/org/springframework/core/io/UrlResource.java

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ public class UrlResource extends AbstractFileResolvingResource {
6666
*/
6767
private volatile @Nullable String cleanedUrl;
6868

69+
/**
70+
* Whether to use URLConnection caches ({@code null} means default).
71+
*/
72+
@Nullable
73+
volatile Boolean useCaches;
74+
6975

7076
/**
7177
* Create a new {@code UrlResource} based on the given URL object.
@@ -215,11 +221,22 @@ private String getCleanedUrl() {
215221
return cleanedUrl;
216222
}
217223

224+
/**
225+
* Set an explicit flag for {@link URLConnection#setUseCaches},
226+
* to be applied for any {@link URLConnection} operation in this resource.
227+
* <p>By default, caching will be applied only to jar resources.
228+
* An explicit {@code true} flag applies caching to all resources, whereas an
229+
* explicit {@code false} flag turns off caching for jar resources as well.
230+
* @since 6.2.10
231+
* @see ResourceUtils#useCachesIfNecessary
232+
*/
233+
public void setUseCaches(boolean useCaches) {
234+
this.useCaches = useCaches;
235+
}
236+
218237

219238
/**
220239
* This implementation opens an InputStream for the given URL.
221-
* <p>It sets the {@code useCaches} flag to {@code false},
222-
* mainly to avoid jar file locking on Windows.
223240
* @see java.net.URL#openConnection()
224241
* @see java.net.URLConnection#setUseCaches(boolean)
225242
* @see java.net.URLConnection#getInputStream()
@@ -250,6 +267,17 @@ protected void customizeConnection(URLConnection con) throws IOException {
250267
}
251268
}
252269

270+
@Override
271+
void useCachesIfNecessary(URLConnection con) {
272+
Boolean useCaches = this.useCaches;
273+
if (useCaches != null) {
274+
con.setUseCaches(useCaches);
275+
}
276+
else {
277+
super.useCachesIfNecessary(con);
278+
}
279+
}
280+
253281
/**
254282
* This implementation returns the underlying URL reference.
255283
*/
@@ -304,7 +332,9 @@ public File getFile() throws IOException {
304332
*/
305333
@Override
306334
public Resource createRelative(String relativePath) throws MalformedURLException {
307-
return new UrlResource(createRelativeURL(relativePath));
335+
UrlResource resource = new UrlResource(createRelativeURL(relativePath));
336+
resource.useCaches = this.useCaches;
337+
return resource;
308338
}
309339

310340
/**

spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
259259

260260
private PathMatcher pathMatcher = new AntPathMatcher();
261261

262-
private boolean useCaches = true;
262+
@Nullable
263+
private Boolean useCaches;
263264

264265
private final Map<String, Resource[]> rootDirCache = new ConcurrentHashMap<>();
265266

@@ -339,10 +340,12 @@ public PathMatcher getPathMatcher() {
339340
* the {@link JarURLConnection} level as well as within this resolver instance.
340341
* <p>Note that {@link JarURLConnection#setDefaultUseCaches} can be turned off
341342
* independently. This resolver-level setting is designed to only enforce
342-
* {@code JarURLConnection#setUseCaches(false)} if necessary but otherwise
343-
* leaves the JVM-level default in place.
343+
* {@code JarURLConnection#setUseCaches(true/false)} if necessary but otherwise
344+
* leaves the JVM-level default in place (if this setter has not been called).
345+
* <p>As of 6.2.10, this setting propagates to {@link UrlResource#setUseCaches}.
344346
* @since 6.1.19
345347
* @see JarURLConnection#setUseCaches
348+
* @see UrlResource#setUseCaches
346349
* @see #clearCache()
347350
*/
348351
public void setUseCaches(boolean useCaches) {
@@ -352,7 +355,11 @@ public void setUseCaches(boolean useCaches) {
352355

353356
@Override
354357
public Resource getResource(String location) {
355-
return getResourceLoader().getResource(location);
358+
Resource resource = getResourceLoader().getResource(location);
359+
if (this.useCaches != null && resource instanceof UrlResource urlResource) {
360+
urlResource.setUseCaches(this.useCaches);
361+
}
362+
return resource;
356363
}
357364

358365
@Override
@@ -470,20 +477,27 @@ protected Resource convertClassLoaderURL(URL url) {
470477
}
471478
}
472479
else {
480+
UrlResource resource = null;
473481
String urlString = url.toString();
474482
String cleanedPath = StringUtils.cleanPath(urlString);
475483
if (!cleanedPath.equals(urlString)) {
476484
// Prefer cleaned URL, aligned with UrlResource#createRelative(String)
477485
try {
478486
// Retain original URL instance, potentially including custom URLStreamHandler.
479-
return new UrlResource(new URL(url, cleanedPath));
487+
resource = new UrlResource(new URL(url, cleanedPath));
480488
}
481489
catch (MalformedURLException ex) {
482490
// Fallback to regular URL construction below...
483491
}
484492
}
485493
// Retain original URL instance, potentially including custom URLStreamHandler.
486-
return new UrlResource(url);
494+
if (resource == null) {
495+
resource = new UrlResource(url);
496+
}
497+
if (this.useCaches != null) {
498+
resource.setUseCaches(this.useCaches);
499+
}
500+
return resource;
487501
}
488502
}
489503

@@ -502,6 +516,9 @@ protected void addAllClassLoaderJarRoots(@Nullable ClassLoader classLoader, Set<
502516
UrlResource jarResource = (ResourceUtils.URL_PROTOCOL_JAR.equals(url.getProtocol()) ?
503517
new UrlResource(url) :
504518
new UrlResource(ResourceUtils.JAR_URL_PREFIX + url + ResourceUtils.JAR_URL_SEPARATOR));
519+
if (this.useCaches != null) {
520+
jarResource.setUseCaches(this.useCaches);
521+
}
505522
if (jarResource.exists()) {
506523
result.add(jarResource);
507524
}
@@ -553,7 +570,7 @@ protected void addClassPathManifestEntries(Set<Resource> result) {
553570
Set<ClassPathManifestEntry> entries = this.manifestEntriesCache;
554571
if (entries == null) {
555572
entries = getClassPathManifestEntries();
556-
if (this.useCaches) {
573+
if (this.useCaches == null || this.useCaches) {
557574
this.manifestEntriesCache = entries;
558575
}
559576
}
@@ -574,7 +591,7 @@ private Set<ClassPathManifestEntry> getClassPathManifestEntries() {
574591
try {
575592
File jar = new File(path).getAbsoluteFile();
576593
if (jar.isFile() && seen.add(jar)) {
577-
manifestEntries.add(ClassPathManifestEntry.of(jar));
594+
manifestEntries.add(ClassPathManifestEntry.of(jar, this.useCaches));
578595
manifestEntries.addAll(getClassPathManifestEntriesFromJar(jar));
579596
}
580597
}
@@ -613,7 +630,7 @@ private Set<ClassPathManifestEntry> getClassPathManifestEntriesFromJar(File jar)
613630
}
614631
File candidate = new File(parent, path);
615632
if (candidate.isFile() && candidate.getCanonicalPath().contains(parent.getCanonicalPath())) {
616-
manifestEntries.add(ClassPathManifestEntry.of(candidate));
633+
manifestEntries.add(ClassPathManifestEntry.of(candidate, this.useCaches));
617634
}
618635
}
619636
}
@@ -707,7 +724,7 @@ else if (commonPrefix.equals(rootDirPath)) {
707724
if (rootDirResources == null) {
708725
// Lookup for specific directory, creating a cache entry for it.
709726
rootDirResources = getResources(rootDirPath);
710-
if (this.useCaches) {
727+
if (this.useCaches == null || this.useCaches) {
711728
this.rootDirCache.put(rootDirPath, rootDirResources);
712729
}
713730
}
@@ -726,7 +743,11 @@ else if (commonPrefix.equals(rootDirPath)) {
726743
if (resolvedUrl != null) {
727744
rootDirUrl = resolvedUrl;
728745
}
729-
rootDirResource = new UrlResource(rootDirUrl);
746+
UrlResource urlResource = new UrlResource(rootDirUrl);
747+
if (this.useCaches != null) {
748+
urlResource.setUseCaches(this.useCaches);
749+
}
750+
rootDirResource = urlResource;
730751
}
731752
if (rootDirUrl.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
732753
result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirUrl, subPattern, getPathMatcher()));
@@ -862,8 +883,8 @@ protected Set<Resource> doFindPathMatchingJarResources(Resource rootDirResource,
862883

863884
if (con instanceof JarURLConnection jarCon) {
864885
// Should usually be the case for traditional JAR files.
865-
if (!this.useCaches) {
866-
jarCon.setUseCaches(false);
886+
if (this.useCaches != null) {
887+
jarCon.setUseCaches(this.useCaches);
867888
}
868889
try {
869890
jarFile = jarCon.getJarFile();
@@ -928,7 +949,7 @@ protected Set<Resource> doFindPathMatchingJarResources(Resource rootDirResource,
928949
}
929950
}
930951
}
931-
if (this.useCaches) {
952+
if (this.useCaches == null || this.useCaches) {
932953
// Cache jar entries in TreeSet for efficient searching on re-encounter.
933954
this.jarEntriesCache.put(jarFileUrl, entriesCache);
934955
}
@@ -1251,10 +1272,10 @@ private record ClassPathManifestEntry(Resource resource, @Nullable Resource alte
12511272

12521273
private static final String JARFILE_URL_PREFIX = ResourceUtils.JAR_URL_PREFIX + ResourceUtils.FILE_URL_PREFIX;
12531274

1254-
static ClassPathManifestEntry of(File file) throws MalformedURLException {
1275+
static ClassPathManifestEntry of(File file, @Nullable Boolean useCaches) throws MalformedURLException {
12551276
String path = fixPath(file.getAbsolutePath());
1256-
Resource resource = asJarFileResource(path);
1257-
Resource alternative = createAlternative(path);
1277+
Resource resource = asJarFileResource(path, useCaches);
1278+
Resource alternative = createAlternative(path, useCaches);
12581279
return new ClassPathManifestEntry(resource, alternative);
12591280
}
12601281

@@ -1274,18 +1295,22 @@ private static String fixPath(String path) {
12741295
* @param path the file path (with or without a leading slash)
12751296
* @return the alternative form or {@code null}
12761297
*/
1277-
private static @Nullable Resource createAlternative(String path) {
1298+
private static @Nullable Resource createAlternative(String path, @Nullable Boolean useCaches) {
12781299
try {
12791300
String alternativePath = path.startsWith("/") ? path.substring(1) : "/" + path;
1280-
return asJarFileResource(alternativePath);
1301+
return asJarFileResource(alternativePath, useCaches);
12811302
}
12821303
catch (MalformedURLException ex) {
12831304
return null;
12841305
}
12851306
}
12861307

1287-
private static Resource asJarFileResource(String path) throws MalformedURLException {
1288-
return new UrlResource(JARFILE_URL_PREFIX + path + ResourceUtils.JAR_URL_SEPARATOR);
1308+
private static Resource asJarFileResource(String path, @Nullable Boolean useCaches) throws MalformedURLException {
1309+
UrlResource resource = new UrlResource(JARFILE_URL_PREFIX + path + ResourceUtils.JAR_URL_SEPARATOR);
1310+
if (useCaches != null) {
1311+
resource.setUseCaches(useCaches);
1312+
}
1313+
return resource;
12891314
}
12901315
}
12911316

spring-webmvc/src/test/java/org/springframework/web/servlet/resource/PathResourceResolverTests.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -184,21 +184,19 @@ private static class TestUrlResource extends UrlResource {
184184

185185
private String relativePath;
186186

187-
188187
public TestUrlResource(String path) throws MalformedURLException {
189188
super(path);
190189
}
191190

192-
193-
public String getSavedRelativePath() {
194-
return this.relativePath;
195-
}
196-
197191
@Override
198192
public Resource createRelative(String relativePath) {
199193
this.relativePath = relativePath;
200194
return this;
201195
}
196+
197+
public String getSavedRelativePath() {
198+
return this.relativePath;
199+
}
202200
}
203201

204202
}

0 commit comments

Comments
 (0)