AspectJ和CDI [英] AspectJ and CDI
问题描述
我正试图找出一种方法来将bean注入一个方面。
I'm trying to figure out a way to inject a bean into an aspect.
我的意思是
public class Greeter {
public String greet(String name) {....}
}
...
public aspect GreeterAspect {
@Inject
private Greeter greeter
...
}
使用Arquillian + Wildfly 8.2.1(托管和远程)将其作为JUnit测试执行我得到以下日志行:
Executing that as a JUnit test with Arquillian + Wildfly 8.2.1 (managed and remote) I get these lines of log:
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构建)。在提供
范围内,尝试切换到编译
但没有改变。
If I get it right, it complains that aspectjrt.jar is not in the classpath, though I've checked and I got it in the dependencies (using Maven to build). Was in provided
scope, tried to switch to compile
but nothing changed.
任何人都可以帮我解决这个问题吗?
Can anyone help me solve the issue?
编辑:解决了初始问题,现在是NullPointerException
按照simas_ch的建议,通过将 aspectjrt.jar
添加到Arquillian部署来解决初始问题。
Solved the initial issue by adding the aspectjrt.jar
to Arquillian deployment as suggested by simas_ch.
但是,在执行时,我收到 NullPointerException
Though, when executing, I receive a 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即将说些什么...
)然后我得到 NullPointerException
,显然 Greeter
bean尚未注入。
I can see the first log line (Aspect is about to say something...
) and then I get the NullPointerException
, clearly the Greeter
bean has not been injected.
我做错了什么?或者是否可以将bean注入各个方面?
What am I doing wrong? Or is it possible at all to inject beans into aspects?
推荐答案
感谢社区的帮助,我成功地走了出来解决这两个问题。离开这里。
Thanks to the help of the community, I managed to come out with a solution for both the problems. Leaving track here.
第一部分 - 部署中的aspectjrt.jar
首先,将 Shrinkwrap
添加到我的依赖项中:
First, added Shrinkwrap
to my dependencies:
<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
- 已经包含在内 - 将负责处理。
<version>
is not needed: Arquillian's BOM
- already included - will take care of that.
然后添加 aspectj
到部署类路径:
Then add aspectj
to deployment classpath:
@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
}
第二部分:将豆子注入方面
经过进一步调查后,我认为simas_ch说得对CDI不会将bean注入方面。
After further inquiries I think simas_ch was correct in saying that CDI does not inject beans into aspects.
出现一种解决方法:将 @Inject
ed成员添加到通过方面的bean。
Came out with a workaround: adding an @Inject
ed member into a bean via the aspect.
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."));
}
成功。
这篇关于AspectJ和CDI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!