Mastering Spring’s @Autowired for Collections: From Lists to Maps

This article explains how Spring’s @Autowired can inject List, Set, and Map collections, detailing injection mechanisms, code examples, workflow steps, common use cases like plugin systems and filter chains, and advanced tips such as @Qualifier, custom ordering, and handling pitfalls.

Xuanwu Backend Tech Stack
Xuanwu Backend Tech Stack
Xuanwu Backend Tech Stack
Mastering Spring’s @Autowired for Collections: From Lists to Maps

Spring @Autowired on Collections

Spring’s @Autowired annotation can be applied to collection types such as List , Set , and Map . When used on a collection, Spring automatically discovers all beans of the element type and injects them into the collection.

This mechanism is ideal for plugin architectures, filter chains, multi‑strategy implementations, and other scenarios that require loose coupling and automatic aggregation of multiple implementations.

Common collection injection forms: List<BeanType> – injects all matching beans, preserving order and allowing duplicates. Set<BeanType> – injects all matching beans without duplicates. Map<String, BeanType> – injects beans with their bean name as the key. Map<Class<?>, BeanType> – injects beans with their type as the key.

Detailed Parsing

1. List Injection

When a @Autowired List is injected, Spring collects all matching beans and orders them according to @Order or the Ordered interface.

package com.qy.filter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.util.List;

// 过滤器接口
public interface RequestFilter {
    String filter(String request);
}

// 安全过滤器
@Component
@Order(1) // 指定顺序为1,最先执行
class SecurityFilter implements RequestFilter {
    @Override
    public String filter(String request) {
        System.out.println("执行安全过滤");
        return request + " [已安全过滤]";
    }
}

// 日志过滤器
@Component
@Order(2) // 指定顺序为2,第二执行
class LoggingFilter implements RequestFilter {
    @Override
    public String filter(String request) {
        System.out.println("执行日志记录");
        return request + " [已记录日志]";
    }
}

// 缓存过滤器
@Component
@Order(3) // 指定顺序为3,最后执行
class CachingFilter implements RequestFilter {
    @Override
    public String filter(String request) {
        System.out.println("执行缓存处理");
        return request + " [已缓存]";
    }
}

// 过滤器链服务
@Service
public class FilterChainService {
    private final List<RequestFilter> filters;

    @Autowired
    public FilterChainService(List<RequestFilter> filters) {
        this.filters = filters;
        System.out.println("已注入过滤器数量:" + filters.size());
    }

    public String processRequest(String request) {
        String result = request;
        for (RequestFilter filter : filters) {
            result = filter.filter(result);
        }
        return result;
    }
}

2. Set Injection

Set injection works like List but eliminates duplicate beans.

package com.qy.validator;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.util.Set;

// 验证器接口
public interface Validator {
    boolean validate(String data);
    String getValidatorName();
}

// 非空验证器
@Component
class NotEmptyValidator implements Validator {
    @Override
    public boolean validate(String data) {
        boolean valid = data != null && !data.trim().isEmpty();
        System.out.println("非空验证: " + (valid ? "通过" : "失败"));
        return valid;
    }
    @Override
    public String getValidatorName() {
        return "非空验证器";
    }
}

// 长度验证器
@Component
class LengthValidator implements Validator {
    @Override
    public boolean validate(String data) {
        boolean valid = data != null && data.length() <= 100;
        System.out.println("长度验证: " + (valid ? "通过" : "失败"));
        return valid;
    }
    @Override
    public String getValidatorName() {
        return "长度验证器";
    }
}

// 验证服务
@Service
public class ValidationService {
    private final Set<Validator> validators;

    @Autowired
    public ValidationService(Set<Validator> validators) {
        this.validators = validators;
        System.out.println("已注入验证器:");
        validators.forEach(v -> System.out.println("- " + v.getValidatorName()));
    }

    public boolean validate(String data) {
        return validators.stream().allMatch(v -> v.validate(data));
    }
}

3. Map<String, BeanType> Injection

Map injection uses the bean name as the key.

package com.qy.processor;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.util.Map;

// 处理器接口
public interface DataProcessor {
    String process(String data);
}

// JSON处理器
@Component("json")
class JsonProcessor implements DataProcessor {
    @Override
    public String process(String data) {
        System.out.println("处理JSON数据");
        return "{\"processed\": \"" + data + "\"}";
    }
}

// XML处理器
@Component("xml")
class XmlProcessor implements DataProcessor {
    @Override
    public String process(String data) {
        System.out.println("处理XML数据");
        return "<processed>" + data + "</processed>";
    }
}

// 处理服务
@Service
public class ProcessorService {
    private final Map<String, DataProcessor> processorMap;

    @Autowired
    public ProcessorService(Map<String, DataProcessor> processorMap) {
        this.processorMap = processorMap;
        System.out.println("已注入数据处理器:" + processorMap.keySet());
    }

    public String processData(String type, String data) {
        DataProcessor processor = processorMap.get(type);
        if (processor != null) {
            return processor.process(data);
        } else {
            throw new IllegalArgumentException("不支持的数据类型:" + type);
        }
    }
}

How Collection Injection Works

Identify collection type : Spring detects that the injection point is a List, Set, or Map.

Determine element type : Generic information is used to find the element class.

Collect matching beans : All beans of that type are retrieved from the container.

Order if needed : For Lists, beans are sorted by @Order or Ordered.

Inject collection : The assembled collection is injected into the target.

An illustrative flow diagram:

Typical Use Cases

Plugin systems – automatic discovery and registration.

Filter/Interceptor chains – ordered processing pipelines.

Multiple strategy implementations – select implementation based on conditions.

Command handlers – route commands to appropriate processors.

Validator collections – combine several validation rules.

Event listeners – auto‑register listeners.

Advanced Features & Caveats

1. Precise control with @Qualifier

When multiple beans of the same type exist, @Qualifier can limit which beans are injected.

@Autowired
@Qualifier("highPriority")
private List<TaskProcessor> highPriorityProcessors;

2. Custom ordering

Beyond @Order, implementing Ordered or PriorityOrdered gives fine‑grained control.

@Component
public class CriticalFilter implements RequestFilter, PriorityOrdered {
    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE; // highest priority
    }
    @Override
    public String filter(String request) {
        // implementation
    }
}

3. Generic type qualifiers

Spring can narrow injection by generic type, e.g., injecting only Repository<User> beans.

interface Repository<T> { /* ... */ }

@Component
class UserRepository implements Repository<User> { /* ... */ }

@Component
class ProductRepository implements Repository<Product> { /* ... */ }

@Service
class Service {
    @Autowired
    private List<Repository<User>> userRepositories; // only UserRepository injected
}

4. Important considerations

Circular dependencies : Collection injection may introduce circular references.

Performance impact : Large numbers of beans can increase startup time.

Order stability : Unordered collections have nondeterministic ordering.

Empty collections : If no matching beans are found, Spring injects an empty collection rather than null.

Springdependency-injection@AutowiredCollection Injection
Xuanwu Backend Tech Stack
Written by

Xuanwu Backend Tech Stack

Primarily covers fundamental Java concepts, mainstream frameworks, deep dives into underlying principles, and JVM internals.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.