我倾向于CDI Annotation有关于Produces Annotation的问题:
我有一个银行
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 {
}
Enum
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异常。 InjectionPoint是空的。问题是什么,如何解决?
替代解决方案:尝试焊接
<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/
答案 0 :(得分:0)
正如我在帖子评论中已经提到的,CDI实施似乎有效。我认为问题在于测试。最初,我刚用main()
方法编写了一个简单的测试,一切正常。现在我将相同的代码移动到JUnit测试,它仍然有效。为了测试您的实现,我刚刚为您的工厂和测试类添加了以下客户端,如下所示:
public class BankClient {
@Inject
@BankProducer
@BankType(BankName.BankOfAmerica)
private Bank bankOfAmerica;
public void deposit() {
bankOfAmerica.deposit();
}
public void withdrawal() {
bankOfAmerica.withdrawal();
}
}
// JUnit test
public class BankServiceTest {
private static Weld weld = new Weld();
private static BankClient sut;
@BeforeClass
public static void initWeld() {
WeldContainer container = weld.initialize();;
sut = container.instance().select(BankClient.class).get();
}
@Test
public void deposit_should_be_invoked() {
sut.deposit();
}
@Test
public void withdrawal_should_be_called() {
sut.withdrawal();
}
@AfterClass
public static void shutDown() {
weld.shutdown();
}
}
执行测试后,您应该在控制台和JUnit绿色栏上看到以下输出:
您存入美国银行
您正在退出美国银行