CDI:@ Inject,限定符,@ Produces,差异实现

时间:2015-06-07 15:35:17

标签: java-ee dependency-injection cdi

我想有基于某些条件的CD @Produces方法正在生成ZipCodeChecker实现的合适实现。它是CountryZipCodeChecker的正确实例化实现,CountryZipCodeValidator使用它来验证适合于Address实体中的地址集的邮政编码。我做了这样的事情:

   public class CountryZipCodeValidator implements ConstraintValidator<CountryZipCode, Address> {

    private static final Logger logger = Logger.getLogger(CountryZipCodeValidator.class.getName());

    @Inject
    private Instance<ZipCodeChecker> checkerInstance;

    @Override
    public void initialize(CountryZipCode constraintAnnotation) {

    }

    @Override
    public boolean isValid(Address value, ConstraintValidatorContext context) {

        logger.log(Level.INFO, "Validating zip code format for typed country.");

        if(value.getZipCode() == null || value.getCountry() == null)
            return true;

        // selecting ZipCodeChecker instance specific to country name set in Address object
        ZipCodeChecker checker = checkerInstance.select(new CountryQualifierLiteral(value.getCountry())).get();

        return checker.isFormatValid(value.getZipCode());
     }
   }

ZipCodeCheckerFactory @Produces 合适 ZipCodeChecker

    public class ZipCodeCheckerFactory {

    @Inject
    CountryZipCodeChecker countryZipCodeChecker;

    @Produces
    public ZipCodeChecker createZipCodeChecker(InjectionPoint injectionPoint) {

        // retrieving country name from injection point to return country specific checker instance
        Country countryQualifier = injectionPoint.getAnnotated().getAnnotation(Country.class);
        String countryName = countryQualifier.value();

        countryZipCodeChecker.setCountryName(countryName);

        return countryZipCodeChecker;
    }

}

这里是 CountryZipCodeChecker

的摘录
public class CountryZipCodeChecker implements ZipCodeChecker { /*...*/}

这里是ZipCodeChecker接口:

    public interface ZipCodeChecker {

    public boolean isFormatValid(String zipCode);
}

和限定符实现:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER,})
public @interface Country {

    @Nonbinding String value() default "United States";
}

我在尝试调用@Injected zipCodeChecker.isValid()方法时遇到这样的错误和NullPointer异常:

 org.jboss.arquillian.test.spi.ArquillianProxyException: org.jboss.weld.exceptions.IllegalArgumentException : WELD-001302: Duplicate qualifiers:  [@pl.salonea.qualifiers.Country(value=United States)] [Proxied because : Original exception not deserilizable, ClassNotFoundException]
    at org.jboss.weld.resolution.ResolvableBuilder.checkQualifier(ResolvableBuilder.java:210)
    at org.jboss.weld.resolution.ResolvableBuilder.addQualifier(ResolvableBuilder.java:177)
    at org.jboss.weld.resolution.ResolvableBuilder.addQualifiers(ResolvableBuilder.java:200)

1 个答案:

答案 0 :(得分:0)

根据您的用例,您真的不需要这里的制作人。您需要使用实例注入:

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, TYPE, PARAMETER})
public @interface ZipCodeCheck {

   //The country which this zipcodecher can validate
   Country value();
}

public class ZipCodeCheckImpl extends AnnotationLiteral<ZipCodeCheck> implements ZipCodeCheck {
   private final Country country;

   public ZipCodeCheckImpl(final Country country) {
     this.country = country;
   }

   public Country value() {
     return country;
   }
}

public interface ZipCoderChecker {

   boolean isValid(final String zipcode);
}

两个实现

@ApplicationScoped
@ZipCodeCheck(USA)
public class USZipCodeChecker implements ZipCoderChecker {
}


@ApplicationScoped
@ZipCodeCheck(GB)
public class GBZipCodeChecker implements ZipCoderChecker {
}

用法:

@ApplicationScoped
public class CounryZipCodeValidator {

  @Any
  @Inject
  private Instance<ZipCodeChecker> zipCodeCheckers;

  public void validate(final Address address) {
    Country country = address.getCountry();
    ZipCodeChecker zipCodeChecker = zipCodeCheckers.select(new ZipCodeCheckImpl(country)).get(); //will return null if no zipcoderchecker for the country.
    checkState(zipCodeChecker.isValid(address.getZipCode()), "Invalid zipcode");
  }
}