How do you obtain a ResourceLoader / ResourcePatternResolver inside a bean, and how does PathMatchingResourcePatternResolver fit in?
answer
- ApplicationContext IS-A ResourcePatternResolver IS-A ResourceLoader
- @Autowired the loader = Spring injects itself
- ResourceLoaderAware setter callback
- PathMatchingResourcePatternResolver + AntPathMatcher (? * **)
- getResources() for wildcards, getResource() for one
basics
~10 sJust autowire ResourceLoader (or ResourcePatternResolver) — the ApplicationContext implements both, so Spring injects itself. For wildcard scanning use ResourcePatternResolver.getResources(), which is backed by PathMatchingResourcePatternResolver.
solid answer
~30 sBecause `ApplicationContext extends ResourcePatternResolver extends ResourceLoader`, the container *is* the loader. To get it inside a bean you can `@Autowired`/constructor-inject `ResourceLoader` or `ResourcePatternResolver` directly, or implement the `ResourceLoaderAware` callback interface (Spring calls `setResourceLoader` during initialization). For single locations use `getResource(String)`; for wildcard/`classpath*:` patterns cast/inject `ResourcePatternResolver` and call `getResources(String)`, returning `Resource[]`. The default implementation behind an `ApplicationContext` is `PathMatchingResourcePatternResolver`, which understands Ant-style patterns (`?`, `*`, `**`) and `classpath*:`. You can also instantiate it standalone (`new PathMatchingResourcePatternResolver()`) outside a Spring context and optionally hand it a specific `ClassLoader` or a delegate `ResourceLoader`.
code
kotlin · 14 linesimport org.springframework.core.io.Resource
import org.springframework.core.io.support.ResourcePatternResolver
import org.springframework.stereotype.Component
@Component
class MigrationScriptLoader(
// The ApplicationContext is injected here (it implements the interface).
private val resolver: ResourcePatternResolver,
) {
fun sqlScripts(): List<Resource> =
resolver.getResources("classpath*:db/migration/**/*.sql")
.filter { it.isReadable }
.sortedBy { it.filename }
}go deeper
Should know you can @Autowired ResourceLoader and call getResource().
Should distinguish ResourceLoader vs ResourcePatternResolver and name PathMatchingResourcePatternResolver for wildcards.
Should explain the ApplicationContext type hierarchy, ResourceLoaderAware, and standalone resolver construction with a custom ClassLoader.
Considers when standalone resolution (build tools, non-Spring contexts) is appropriate vs container-managed, and the classloader implications.
## The type hierarchy that makes this work ``` ResourceLoader // getResource(String) ^ ResourcePatternResolver // + getResources(String) : Resource[] ^ ApplicationContext // is-a ResourcePatternResolver ``` Because the `ApplicationContext` sits at the bottom, **the context is itself a resource loader and pattern resolver**. That's why you never construct one to load application resources — you ask the container. ## Three ways to get the loader into a bean **1. Constructor / field injection (preferred).** Spring resolves `ResourceLoader` and `ResourcePatternResolver` dependencies to the context itself: ```java @Component class Seeder { private final ResourcePatternResolver resolver; Seeder(ResourcePatternResolver resolver) { this.resolver = resolver; } } ``` **2. `ResourceLoaderAware` callback.** Implement the interface and Spring injects via a setter during bean initialization (an `*Aware` interface processed by `ApplicationContextAwareProcessor`): ```java class Seeder implements ResourceLoaderAware { private ResourceLoader loader; public void setResourceLoader(ResourceLoader l) { this.loader = l; } } ``` **3. Inject a Resource directly** when you know the location at wiring time: `@Value("classpath:seed.json") Resource seed;` (no loader reference needed). ## PathMatchingResourcePatternResolver `org.springframework.core.io.support.PathMatchingResourcePatternResolver` is the concrete `ResourcePatternResolver` used everywhere. Responsibilities: - Delegates non-pattern locations to a wrapped `ResourceLoader` (a `DefaultResourceLoader` by default). - Recognizes `classpath*:` and expands it via `ClassLoader.getResources`. - Matches Ant patterns using an `AntPathMatcher`: `?` (one char), `*` (within a segment), `**` (across segments). - Walks directories/JARs to enumerate matches for patterns like `classpath*:config/**/*.xml`. You can use it **standalone**, outside any Spring container: ```java var resolver = new PathMatchingResourcePatternResolver(); // uses default classloader var r2 = new PathMatchingResourcePatternResolver(myClassLoader); var r3 = new PathMatchingResourcePatternResolver(existingResourceLoader); Resource[] xml = resolver.getResources("classpath*:META-INF/*.xml"); ``` ## getResource vs getResources - `getResource(location)` -> exactly one `Resource`, no wildcard expansion, never null. - `getResources(pattern)` -> `Resource[]`, expands wildcards and `classpath*:`. For a non-pattern location it returns an array of length 1 (or the aggregated set for `classpath*:`). ## Gotchas - Injecting `ResourceLoader` gives you only `getResource`; if you need wildcards, inject `ResourcePatternResolver`. - The injected loader **is** the context — its no-prefix path resolution follows the context type (classpath for a generic/annotation context). - Standalone `PathMatchingResourcePatternResolver` won't see Spring's environment or profile-specific config; it's pure resource lookup. - `getResources` can return resources that don't exist only in edge JAR cases; still check `exists()` when reading.
- If you inject ResourceLoader instead of ResourcePatternResolver, can you still resolve classpath*: patterns?No — ResourceLoader only exposes getResource(), which returns a single Resource and ignores wildcard/classpath*: expansion. Inject ResourcePatternResolver (or the ApplicationContext) to get getResources().
saying these in an interview costs you the question
- Manually constructing an ApplicationContext just to get a ResourceLoader inside a managed bean.
- Thinking ResourceLoader can expand wildcards (only ResourcePatternResolver.getResources can).
- Assuming a standalone PathMatchingResourcePatternResolver honors Spring profiles/environment.