AspectJ和CDI [英] AspectJ and CDI

查看:194
本文介绍了AspectJ和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 @Injected 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆