当前位置: 首页 > 面试题库 >

AspectJ和CDI

公冶智刚
2023-03-14
问题内容

我试图找出一种将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.jarsimas_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,显然该Greeterbean没有被注入。

我究竟做错了什么?还是有可能将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."));
}

成功了。



 类似资料:
  • AspectJ是一个面向方面的框架,它扩展了Java语言。AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。

  • 我正在使用Spring 3.1.1版的应用程序中工作,现在我需要为其添加一些方面。这些方面是用aspectj语言编写的,没有注释。我已经阅读了Spring docs第8.8章,但我正在努力使其工作。 我的spring配置如下所示: 在我的pom中,是一个Maven项目,我有spring aop、aspectjrt和aspectjweaver作为依赖项。 我的问题是,当启动应用程序时,我得到了一个

  • 我想一起使用AEX J AOP和Spring(用于DI),但我得到以下例外: 我使用IntelliJ IDEA 12 Ultimate IDE 以下是重现错误的示例步骤。 1:信息界面: 2:接口实现: 3:方面: 4:spring配置。xml文件: 5:我在以下主要课程中运行所有内容: ...我得到一个错误: 我做错了什么

  • @AspectJ指的是将方面声明为使用Java 5注释注释的常规Java类的样式。 通过在基于XML模式的配置文件中包含以下元素来启用@AspectJ支持。 <aop:aspectj-autoproxy/> 您还需要在应用程序的类路径上使用以下AspectJ库。 这些库位于AspectJ安装的“lib”目录中,否则您可以从Internet下载它们。 aspectjrt.jar aspectjwe

  • 我想把@AutoWired注释变成一个“方面”。我想在我的方面中注入一个存储库,但是当我试图调用autowired类的方法时,出现了NullPointException。 我已经尝试在aspect类上添加,但我出现了同样的错误。 如果我不使用aspect类,而是使用,我可以毫无问题地调用存储库。 一些文档谈到了spring的xml文件配置,但在spring boot,我没有这些文件。 这里是pom