如何在Spring中动态自动装配Bean

1.介绍

介绍如何在 Spring 中动态地自动装配 bean。

首先展示一个动态自动装配可能会有所帮助的真实用例。 除此之外,将展示如何在 Spring 中以两种不同的方式解决它。

2.动态自动装配用例

动态自动装配在需要动态更改 Spring 的 bean 执行逻辑的地方很有帮助。 这在根据一些运行时变量选择要执行的代码的地方尤其实用。

为了演示一个真实的用例,创建一个控制世界不同地区的服务器的应用程序。 出于这个原因,创建了一个带有两个简单方法的接口:

public interface RegionService {
    boolean isServerActive(int serverId);

    String getISOCountryCode();
}

两个实现类

@Service("GBregionService")
public class GBRegionService implements RegionService {
    @Override
    public boolean isServerActive(int serverId) {
        return false;
    }

    @Override
    public String getISOCountryCode() {
        return "GB";
    }
}
@Service("USregionService")
public class USRegionService implements RegionService {
    @Override
    public boolean isServerActive(int serverId) {
        return true;
    }

    @Override
    public String getISOCountryCode() {
        return "US";
    }
}

假设有一个网站,用户可以选择检查服务器是否在所选区域中处于活动状态。 因此,希望有一个服务类,在给定用户输入的情况下动态更改 RegionService 接口实现。 毫无疑问,这是动态 bean 自动装配发挥作用的用例。

3.使用BeanFactory

BeanFactory 是用于访问 Spring bean 容器的根接口。 特别是,它包含获取特定 bean 的有用方法。 由于 BeanFactory 也是一个 Spring bean,可以自动装配并直接在类中使用它:

@Service
public class BeanFactoryDynamicAutowireService {
    /**
     * 服务名后缀
     */
    private static final String SERVICE_NAME_SUFFIX = "regionService";
    private final BeanFactory beanFactory;

    @Autowired
    public BeanFactoryDynamicAutowireService(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    public boolean isServerActive(String isoCountryCode, int serverId) {
        RegionService service = beanFactory.getBean(getRegionServiceBeanName(isoCountryCode),
                RegionService.class);

        return service.isServerActive(serverId);
    }

    private String getRegionServiceBeanName(String isoCountryCode) {
        return isoCountryCode + SERVICE_NAME_SUFFIX;
    }
}

使用了 getBean() 方法的重载版本来获取具有给定名称和所需类型的 bean。

虽然这可行,但真的更愿意依赖更惯用的东西; 也就是说,使用依赖注入的东西。

4.使用接口

为了通过依赖注入解决这个问题,将依赖 Spring 鲜为人知的特性之一。

除了标准的单字段自动装配之外,Spring 还能够把特定接口实现的所有 bean 收集到 Map 中:

@Service
public class CustomMapFromListDynamicAutowireService {
    private final Map<String, RegionService> servicesByCountryCode;

    @Autowired
    public CustomMapFromListDynamicAutowireService(List<RegionService> regionServices) {
        servicesByCountryCode = regionServices.stream()
                .collect(Collectors.toMap(RegionService::getISOCountryCode, Function.identity()));
    }

    public boolean isServerActive(String isoCountryCode, int serverId) {
        RegionService service = servicesByCountryCode.get(isoCountryCode);

        return service.isServerActive(serverId);
    }
}

在构造函数中创建了一个map,该map按国家代码保存实现。 此外,可以稍后在方法中使用它来获取特定实现,以检查给定服务器是否在特定区域中处于活动状态。

请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值