AspectJ和CDI

发布于 2021-01-30 15:50:15

我试图找出一种将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注入方面?

关注者
0
被浏览
56
1 个回答
  • 面试哥
    面试哥 2021-01-30
    为面试而生,有面试问题,就找面试哥。

    在社区的帮助下,我设法针对这两个问题提出了解决方案。离开这里。

    第一部分-部署中的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."));
    }
    

    成功了。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看