AspectJ和CDI
我试图找出一种将bean注入方面的方法。
我的意思是
public class Greeter {
public String greet(String name) {....}
}
...
public aspect GreeterAspect {
@Inject
private Greeter greeter
...
}
作为使用Arquillian + Wildfly 8.2.1(托管和远程)的JUnit测试执行,我得到以下日志行:
WELD-000119: Not generating any bean definitions from x.y.z.Greeter because of underlying class loading error: Type org.aspectj.runtime.internal.AroundClosure from [Module "deployment.test.war:main" from Service Module Loader] not found.
WELD-000119: Not generating any bean definitions from x.y.z.GreeterAspect because of underlying class loading error: Type org.aspectj.lang.NoAspectBoundException from [Module "deployment.test.war:main" from Service Module Loader] not found.
我收到错误后不久
WELD-001474: Class x.y.z.Greeter is on the classpath, but was ignored because a class it references was not found: org.aspectj.runtime.internal.AroundClosure from [Module "deployment.test.war:main" from Service Module Loader].
如果我做对了,它会抱怨Aspectjrt.jar不在类路径中,尽管我已经检查过并在依赖项中得到了它(使用Maven构建)。处于provided
范围内,试图切换到compile
但没有任何更改。
谁能帮我解决这个问题?
编辑:解决了最初的问题,现在NullPointerException
通过将aspectjrt.jar
simas_ch建议添加到Arquillian部署中解决了最初的问题。
不过,执行时,我收到一个 NullPointerException
public class Greeter {
public String greet(String name) {....}
}
...
public aspect GreeterAspect {
@Inject
private Greeter greeter;
private pointcut pc() : execution(* x.y.z.SomeClass.someMethod(..));
String around() : pc() {
log.debug("Aspect is about to say something...");
String result = greeter.greet("Stefano");
log.debug("Aspect said: " + result);
return proceed();
}
}
我可以看到第一个日志行(Aspect is about to say
something...
),然后得到NullPointerException
,显然该Greeter
bean没有被注入。
我究竟做错了什么?还是有可能将bean注入方面?
-
在社区的帮助下,我设法针对这两个问题提出了解决方案。离开这里。
第一部分-部署中的Aspectjrt.jar
首先,添加
Shrinkwrap
到我的依赖项:<dependency> <groupId>org.jboss.shrinkwrap.resolver</groupId> <artifactId>shrinkwrap-resolver-api-maven</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.shrinkwrap.resolver</groupId> <artifactId>shrinkwrap-resolver-impl-maven</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.shrinkwrap.resolver</groupId> <artifactId>shrinkwrap-resolver-impl-maven-archive</artifactId> <scope>test</scope> </dependency>
<version>
不需要:Arquillian的BOM
-已经包括了-会解决的。然后添加
aspectj
到部署类路径:@RunWith(Arquillian.class) public class ArquillianTest { private static final String[] DEPENDENCIES = { "org.aspectj:aspectjrt:1.8.7" }; @Deployment public static JavaArchive createEnvironement() { JavaArchive lib = ShrinkWrap.create(JavaArchive.class, "libs.jar"); for (String dependency : DEPENDENCIES) { lib.merge(Maven.resolver().resolve(dependency).withTransitivity().asSingle(JavaArchive.class)); } JavaArchive jar = ShrinkWrap.create(JavaArchive.class) // create you deployment here .as(JavaArchive.class); JavaArchive toBeDeployed = jar.merge(lib); return toBeDeployed; } // other stuff, like tests }
第二部分:将一个bean注入一个方面
经过进一步的查询后,我认为simas_ch是正确的,因为它说CDI不会将bean注入方面。
解决办法:
@Inject
通过方面将ed成员添加到bean中。public interface Advised { String buildGreeting(String name); } public class AdvisedImpl implements Advised { String buildGreeting(String name) { return "ADVISED"; } } public class Greeter { public String greet(String name) { return "Hello, " + name + "."; } } ... public aspect GreeterAspect { @Inject private Greeter Advised.greeter; // adding the member to the interface / class. No need for getters / setters private pointcut pc() : execution(* x.y.z.Advised.buildGreeting(String)); String around(Advised adv, String name) : pc() && target(adv) && args(name) { log.debug("Aspect is about to say something..."); String result = proceed(adv, name) + " - " + adv.greeter.greet(name); log.debug("Aspect said: '" + result + "'"); return result; } }
通过测试
@Test public void test() { assertThat(advised, not(is(nullValue()))); assertThat(advised.buildGreeting("Stefano"), equalToIgnoringCase("advised - hello, stefano.")); }
成功了。