AspectJ and CDI

前端 未结 2 1058
误落风尘
误落风尘 2021-01-14 04:20

I\'m trying to figure out a way to inject a bean into an aspect.

I mean

public class Greeter {
    public String greet(String name) {....}
}

...

pu         


        
相关标签:
2条回答
  • 2021-01-14 04:51

    I'm not familiar with CDI, but if it's not picking up the aspect as a candidate for dependency injection, you should set it manually, preferably as soon as the aspect's dependencies are ready. You can gain access to an aspect (singleton by default), with AspectName.aspectOf().

    Maybe a startup singleton bean similar to this one:

    @Singleton
    @Startup
    public class GreeterAspectSetup {
    
        @Inject
        private Greeter greeter;
    
        @PostConstruct
        private void setupGreeterAspect() {
            GreeterAspect.aspectOf().setGreeter(greeter);
        }
    
    }
    

    Of course, you would have to add the setter for the Greeter to the aspect, or change the field's visibility in the aspect and set it directly.

    0 讨论(0)
  • 2021-01-14 05:02

    Thanks to the help of the community, I managed to come out with a solution for both the problems. Leaving track here.

    PART ONE - aspectjrt.jar in deployment

    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> is not needed: Arquillian's BOM - already included - will take care of that.

    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
    
    }
    

    PART TWO: Injecting a bean into an aspect

    After further inquiries I think simas_ch was correct in saying that CDI does not inject beans into aspects.

    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;
        }
    }
    

    Given the test

    @Test
    public void test() {
        assertThat(advised, not(is(nullValue())));
        assertThat(advised.buildGreeting("Stefano"), equalToIgnoringCase("advised - hello, stefano."));
    }
    

    it succeeds.

    0 讨论(0)
提交回复
热议问题