Weld CDI: как сделать так, чтобы один класс бобов удовлетворял любому из нескольких классификаторов? - PullRequest
2 голосов
/ 22 сентября 2011

Прочитав документы по сварке, я не думаю, что это можно сделать, но я действительно мог бы с этим справиться, поэтому подумал, что могу спросить - если нет способа с CDI, возможно, есть обходной путь для шаблона ...

Я создал пользовательский квалификатор с членом:

@Qualifier
@Target({TYPE, METHOD, FIELD, PARAMETER})
@Retention(RUNTIME)
public @interface JobBinding {
    JobType value();
}

JobType - это перечисление:

public enum JobType {

    JOB_A,
    JOB_B,
// etc - there are quite a few

Скажем, большинство рабочих мест нужно создавать немного по-другому,поэтому у меня есть классы строителей, связанные с работой.Они снабжены аннотацией JobBinding с указанием соответствующего JobType:

@JobBinding(JobType.JOB_A)
public class JobABuilder implements JobBuilder {
....

Когда мне нужно построить, я использую программный поиск:

@Inject @Any
private Instance<JobBuilder> builderSource;
private JobType myJobType;
...
builderSource.select(new JobBindingQualifier(myJobType).get();

JobBindingQualifier - это пользовательский класс:

public class JobBindingQualifier extends AnnotationLiteral<JobBinding> implements JobBinding {

    private static final long serialVersionUID = -822150300665931157L;

    private JobType type;

    public JobBindingQualifier(JobType type) {
        this.type = type;
    }

    @Override
    public JobType value() {
        return type;
   }
}

Пока отлично - CDI работает блестяще.Однако что, если 2 из этих заданий, JOB_X и JOB_Y, построены одинаково?Мне нужен только один класс построителя, экземпляр которого я хотел бы создать для любого из этих параметров - new JobBindingQualifier(JobType.JOB_X) или new JobBindingQualifier(JobType.JOB_Y).

Если я аннотирую JobXAndYBuilder обоими @JobBinding(JOB_X) и @JobBinding(JOB_Y), Я получаю ошибку компилятора о дублированной аннотации.Чтобы обойти это, я мог бы изменить значение аннотации на массив JobTypes, и вы бы аннотировали конструктор, например

@JobBinding(JobType.JOB_X, JobType.JOB_Y)

, с помощью вызываемого там конструктора, используя многоточие для создания массива.Однако, если бы я сделал это, как я мог бы найти это программно, используя любой из типов jobTypes ?Документы по сварке предполагают, что вы должны иметь оба ;Мне нужно предоставить точные аргументы:

builderSource.select(new JobBindingQualifier(JobType.JOB_X, JobType.JOB_Y).get();

, когда я хочу, чтобы либо было достаточно для поиска класса:

builderSource.select(new JobBindingQualifier(JobType.JOB_X).get();
//or
builderSource.select(new JobBindingQualifier(JobType.JOB_Y).get();

Использование массива действительно просто меняет значение, которое выдолжны соответствовать при поиске.Мне действительно нужен способ дважды аннотировать класс одной и той же аннотацией квалификатора, а затем иметь возможность искать его с любой их комбинацией.В противном случае мне придется предоставить класс построителя для X и Y, когда этого будет достаточно.Есть идеи?Заранее спасибо!

1 Ответ

2 голосов
/ 22 октября 2011

Как я уже сказал в своем комментарии, нет прямого способа иметь отношение ИЛИ, когда у вас есть два или более квалификатора в классе бобов.

Таким образом, решение иметь тот же Бин с другим классификатором состоит в том, чтобы использовать механизм источника. В вашем примере вы можете создать свой первый класс как обычно:

@JobBinding(JobType.JOB_X)
public class JobABuilder implements JobBuilder {
    ....
}

и после этого создайте метод продюсера либо в первом классе, либо в выделенном классе продюсеров, как этот

public class MoreJobsProducer {
    @Produces
    @JobBinding(JobType.JOB_Y)
    protected JobBuilder prodJobYBuilder(@New @JobBinding(JobType.JOB_X)
                                         JobBuilder theJob) {
        return theJob;
    }    
}

В параметрах метода продюсера вы вводите свой бывший bean-компонент со своим собственным квалификатором и квалификатором @New, которые создают новый экземпляр bean-компонента, чтобы быть уверенным, что вы избежите некоторых проблем с областями видимости (дополнительную информацию смотрите в документе Weld) .

Это должно сделать "Работа".

...