我扶着CDI標註有一個問題關於可生產譯註:CDI主要生產方法InjectionPoint是空
我有一個銀行
public interface Bank {
public void withdrawal();
public void deposit();
}
兩個實施口味
public class BankOfAmerica implements Bank {
public void withdrawal() {
System.out.println("You are withdrawing from Bank Of America");
}
public void deposit() {
System.out.println("You are depositing in Bank Of America");
}
}
public class Chase implements Bank {
public void withdrawal() {
System.out.println("You are withdrawing from Chase");
}
public void deposit() {
System.out.println("You are depositing in Chase");
}
}
限定符
@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, PARAMETER, FIELD})
public @interface BankProducer {
}
枚舉
public enum BankName {
DCU(DCU.class), Chase(Chase.class), BankOfAmerica(BankOfAmerica.class);
private Class<? extends Bank> bankType;
private BankName(Class<? extends Bank> bankType) {
this.bankType = bankType;
}
public Class<? extends Bank> getBankType() {
return bankType;
}
}
詮釋以結合BANKNAME
@Retention(RUNTIME)
@Target({TYPE, METHOD, PARAMETER, FIELD})
public @interface BankType {
@Nonbinding
BankName value();
}
工廠
public class BankFactory {
@Produces
@BankProducer
public Bank createBank(@Any Instance<Bank> instance, InjectionPoint injectionPoint) {
Annotated annotated = injectionPoint.getAnnotated();
BankType bankTypeAnnotation = annotated.getAnnotation(BankType.class);
Class<? extends Bank> bankType = bankTypeAnnotation.value().getBankType();
return instance.select(bankType).get();
}
}
和一個JUnit
@RunWith(Arquillian.class)
public class ProducesTest {
@Inject
@BankProducer
@BankType(BankName.BankOfAmerica)
private Bank bankOfAmerica;
@Deployment
public static JavaArchive createDeployment() {
return ShrinkWrap.create(JavaArchive.class).addPackages(true, "com.tutorial.produces")
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml").merge(getDependecies());
}
private static JavaArchive getDependecies() {
JavaArchive[] javaArchives = Maven.configureResolver().loadPomFromFile("pom.xml")
.resolve("org.projectlombok:lombok").withTransitivity().as(JavaArchive.class);
JavaArchive mergedLibraries = ShrinkWrap.create(JavaArchive.class);
for (JavaArchive javaArchive : javaArchives) {
mergedLibraries.merge(javaArchive);
}
return mergedLibraries;
}
@Test
public void create() {
assertEquals(banks.getBankOfAmerica().getClass(), BankOfAmerica.class);
}
}
POM - 使用tomee
<dependency>
<groupId>org.apache.tomee</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0-1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomee</groupId>
<artifactId>arquillian-tomee-embedded</artifactId>
<version>7.0.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.shrinkwrap.resolver</groupId>
<artifactId>shrinkwrap-resolver-depchain</artifactId>
<version>2.2.2</version>
<scope>test</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
我在我的工廠createBank方法中得到一個NullPointer異常。注入點是空的。什麼是問題,我該如何解決?
替代的解決方案:嘗試焊接
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se</artifactId>
<version>2.2.8.Final</version>
</dependency>
的JUnit
@RunWith(WeldJUnit4Runner.class)
public class ProducesWeldTest {
@Inject
@BankProducer
@BankType(BankName.BankOfAmerica)
private Bank bankOfAmerica;
@Test
public void create() {
assertEquals(bankOfAmerica.getClass(), BankOfAmerica.class);
}
}
WeldContext和WeldJUnit4Runner都是從這裏 - http://memorynotfound.com/java-se-unit-testing-cdi-junit-jboss-weld-se/
注入點和生產者點的限定符必須匹配。而且你犯了兩個限定詞的錯誤,一個是生產者和一個是注射。它應該是一個。 – maress
我剛剛使用Weld測試了您的實現,並且一切正常。我想你的問題在於你的單元測試。我沒有Arquillian的經驗來判斷它是否能夠初始化和注入bean。 – ujulu
我用POM更新了這篇文章。我正在使用TOMEE – Dingo