简体   繁体   English

Spring,注入仅包含特定 bean 的 bean 列表

[英]Spring, injecting a list of beans with only specific beans included

In Spring, when I inject a list of beans, I only want to inject specific implementations of the interface, when used from different places.在 Spring 中,当我注入一个 beans 列表时,我只想注入接口的特定实现,当从不同的地方使用时。 Is this possible to do?这可能吗? What would be the cleanest way to configure this?配置这个的最干净的方法是什么? For example, I have the following validators:例如,我有以下验证器:

public interface Validator {
    Optional<Error> validate(MultipartFile file);
}

public class Validator1 implements Validator {
    public Optional<Error> validate(MultipartFile file) {
        // do stuff
    }
}

public class Validator2 implements Validator {
    public Optional<Error> validate(MultipartFile file) {
        // do stuff
    }
}

public class Validator3 implements Validator {
    public Optional<Error> validate(MultipartFile file) {
        // do stuff
    }
}

And then I have a validation service which looks similar to this:然后我有一个类似于此的验证服务:

public class ValidationService {
    @Autowired
    private List<Validator> validators;

    public List<Error> validate(MultipartFile file) {
        List<Error> errors = new ArrayList<>();
        validators.forEach(v -> {
            Optional<Error> error = v.validate(file);
            if (error.isPresent()) {
                errors.add(error.get());
            }
        });
        return errors;
    }
}

And then I have some services, which use the ValidationService, eg:然后我有一些使用 ValidationService 的服务,例如:

public class Service1 {

    @Autowired
    private ValidationService validationService;

    public void doStuff(MultipartFile file) {
        ...
        validationService.validate(file);
        ...
    }
}

public class Service2 {

    @Autowired
    private ValidationService validationService;

    public void doStuff(MultipartFile file) {
        ...
        validationService.validate(file);
        ...
    }
}

When Service1 calls validate, I only want Validator1 and Validator2 to have been injected into the ValidatorService.当Service1 调用validate 时,我只想将Validator1 和Validator2 注入到ValidatorService 中。 When Service2 calls validate, I only want Validator2 and Validator3 to have been injected into the ValidatorService.当Service2调用validate时,我只希望Validator2和Validator3已经注入到ValidatorService中。

Hope I have explained this clearly enough.希望我已经解释清楚了。 Thanks in advance for any help offered.在此先感谢您提供的任何帮助。

Create the bean like this with @Qualifier annotations --使用 @Qualifier 注释像这样创建 bean --

@Qualifier("validator1")
public class Validator1 implements Validator {
   public Optional<Error> validate(MultipartFile file) {
            // do stuff
        }
}

@Qualifier("validator2")
public class Validator2 implements Validator {
    public Optional<Error> validate(MultipartFile file) {
        // do stuff
    }
}
@Qualifier("validator3")
public class Validator3 implements Validator {
    public Optional<Error> validate(MultipartFile file) {
        // do stuff
    }
}

and inject it like this ---并像这样注入它---

@Autowired("validator1")
private ValidationService validationService;

Update更新

You can also create a bean collection for all the validators like this -您还可以像这样为所有验证器创建一个 bean 集合 -

@Bean("validators")
public List<Validator> validatorList(Validator1 validator1, Validator2 validator2, Validator3 validator3) {
    return Arrays.asList(validator1, validator2, validator3);
}

and the inject the list bean as --并将列表 bean 注入为 --

@Autowired("validators")
private List<Validator> validators;

Check this page fore a detailed example - https://www.baeldung.com/spring-injecting-collections查看此页面以获得详细示例 - https://www.baeldung.com/spring-injecting-collections

This is likely not the best way to do this.这可能不是执行此操作的最佳方法。 Here is how I would do it, based on my current understanding of Spring.根据我目前对 Spring 的理解,我会这样做。

Summary:概括:

  1. Create a bean method for each collection of implementations.为每个实现集合创建一个 bean 方法。 In your case, create a bean method for a List<Validator> that contains Validator1 and Validator2 and create a second List<Validator> that contains Validator2 and Validator3.在您的情况下,为包含 Validator1 和 Validator2 的List<Validator>创建一个 bean 方法,并创建第二个包含 Validator2 和 Validator3 的List<Validator>
  2. Inject the desired List using @Qualifier.使用@Qualifier 注入所需的列表。

The code should be something like this:代码应该是这样的:

@Configuration
public class ValidatorLists
{
    private void getAndAddBean(
        final ApplicationContext applicationContext,
        final List<Validator> list,
        final String beanName)
    {
        final Validator bean;

        bean = applicationContext.getBean(beanName);
        if (bean != null)
        {
            list.add(bean);
        }
    }

    @Bean("ValidatorList1")
    public List<Validator> validatorList1(final ApplicationContext applicationContext)
    {
        Validator bean;
        final List<Validator> returnValue = new LinkedList<>();

        getAndAddBean(applicationContext, returnValue, "ValidatorImpl1");
        getAndAddBean(applicationContext, returnValue, "ValidatorImpl2");
        
        return returnValue;
    }

    @Bean("ValidatorList2")
    public List<Validator> validatorList2(final ApplicationContext applicationContext)
    {
        Validator bean;
        final List<Validator> returnValue = new LinkedList<>();

        getAndAddBean(applicationContext, returnValue, "ValidatorImpl2");
        getAndAddBean(applicationContext, returnValue, "ValidatorImpl3");
        
        return returnValue;
    }
}

Then reference the list by qualifier.然后通过限定符引用列表。

    @Autowired
    @Qualifier("ValidatorList1")
    private List<Validator> validators;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM