Spring Boot 将 Bean 对象注入到 Map 和 List 中

Spring Boot Spring About 3,534 words

解释

Spring支持将@Service@BeanSpring托管的类,注入到MapList中。

案例

如登陆服务,有一个抽象类LoginService,分别有微信登录和QQ登陆都实现了这个抽象类。

那么在登陆Controller中可以注入Map<String, LoginService>Spring会自动将微信登陆和QQ登陆的实现类按key等于类名,value等于实现类实例的方式注入。

List<LoginService>则是直接注入所有实现类。

代码

public interface LoginService {

    void login(String username, String password);

}

@Service
public class QQLoginService implements LoginService {
    @Override
    public void login(String username, String password) {
        System.out.println("QQLoginService login");
    }
}

@Service
public class WXLoginService implements LoginService{
    @Override
    public void login(String username, String password) {
        System.out.println("WXLoginService login");
    }
}

@RestController
public class LoginController {

    @Resource
    Map<String, LoginService> loginServiceMap;

    @Resource
    List<LoginService> loginServiceList;

    @GetMapping("/login")
    public void login(@RequestParam String type) {
        LoginService loginService = loginServiceMap.get(type);
        loginService.login("username", "password");
        System.out.println("loginServiceMap: " + loginServiceMap);
        System.out.println("loginServiceList: " + loginServiceList);
    }

}

输出

loginServiceMap: {QQLoginService=com.example.controller.QQLoginService@4c7e978c, WXLoginService=com.example.controller.WXLoginService@354e7004}
loginServiceList: [com.example.controller.QQLoginService@4c7e978c, com.example.controller.WXLoginService@354e7004]

源码

DefaultListableBeanFactory中的resolveMultipleBeans方法判断是Map的注入会调用resolveMultipleBeanMap方法。

package org.springframework.beans.factory.support;

public class DefaultListableBeanFactory ... {

    @Nullable
    public Object doResolveDependency(...) throws BeansException {
            
            // Step 3a: multiple beans as stream / array / standard collection / plain map
            Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
            if (multipleBeans != null) {
                return multipleBeans;
            }
    }

    @Nullable
    private Object resolveMultipleBeans(...) {

        Class<?> type = descriptor.getDependencyType();

        if (descriptor instanceof StreamDependencyDescriptor streamDependencyDescriptor) {
            // ...
        } ...
        else if (Map.class == type) {
            return resolveMultipleBeanMap(descriptor, beanName, autowiredBeanNames, typeConverter);
        }

    }

    @Nullable
    private Object resolveMultipleBeanMap(DependencyDescriptor descriptor, @Nullable String beanName,
            @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {

        ResolvableType mapType = descriptor.getResolvableType().asMap();
        Class<?> keyType = mapType.resolveGeneric(0);
        if (String.class != keyType) {
            return null;
        }
        Class<?> valueType = mapType.resolveGeneric(1);
        if (valueType == null) {
            return null;
        }
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
                new MultiElementDescriptor(descriptor));
        if (matchingBeans.isEmpty()) {
            return null;
        }
        if (autowiredBeanNames != null) {
            autowiredBeanNames.addAll(matchingBeans.keySet());
        }
        TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
        return converter.convertIfNecessary(matchingBeans, descriptor.getDependencyType());
    }

}
Views: 11 · Posted: 2026-01-19

———         Thanks for Reading         ———

Give me a Star, Thanks:)

https://github.com/fendoudebb/LiteNote

扫描下方二维码关注公众号和小程序↓↓↓

扫描下方二维码关注公众号和小程序↓↓↓
Prev Post
Today In History
Browsing Refresh