Is it possible to create a JAR with an aspect that is automatically applied to classes in client project?

2.5k views Asked by At

I want to have a JAR with an aspect that intercepts all method calls, e.g.

@Aspect
public class CoolAspect {
    @Pointcut("execution(public * *(..))")
    public void anyPublicMethod() { }

    @Before("anyPublicMethod()")
    public void advice(JoinPoint point) {
       System.out.println("sign:\t" + point.getSignature());
    }
}

Suppose the above is the aspect I have and want clients to use. I compile it to a JAR and make available to Maven.

Now the clients would use this jar as a dependency, e.g.

    <dependency>
        <groupId>cool-group</groupId>
        <artifactId>cool-artifact</artifactId>
        <version>1.0.0</version>
    </dependency>

This artifact (JAR) has the mentioned aspect.

Now is it possible for the aspect work by just declaring a Maven dependency?

Few things that might be important:

  1. I plan to use AspectJ (perhaps Spring AOP, if necessary),
  2. The clients will probably be web applications with normal web.xml etc.
  3. Clients are built with Maven
  4. I want the Clients to be as easy to configure as possible - in my original idea a Maven dependency would be enough.
  5. The "Annotation JAR" will contain a web-fragment, so it's possible to declare some custom ServletContextListener there..

Any ideas?

2

There are 2 answers

4
Mikhail On

No, this is impossible, because AspectJ must be started prior to any client classes. All client classes should be loaded through a special enhanced class loader, which will process annotations.

The other thing is Spring's AOP. it weaves beans during application context start up and does not require special class loader. That would be the easiest way for client if he uses spring. Add maven dependency and then configure AOP in the application context.

There are four types of weaving:

  • Compile-time weaving is the simplest approach. When you have the source code for an application, ajc will compile from source and produce woven class files as output. The invocation of the weaver is integral to the ajc compilation process. The aspects themselves may be in source or binary form. If the aspects are required for the affected classes to compile, then you must weave at compile-time. Aspects are required, e.g., when they add members to a class and other classes being compiled reference the added members.
  • Post-compile weaving (also sometimes called binary weaving) is used to weave existing class files and JAR files. As with compile-time weaving, the aspects used for weaving may be in source or binary form, and may themselves be woven by aspects.
  • Load-time weaving (LTW) is simply binary weaving defered until the point that a class loader loads a class file and defines the class to the JVM. To support this, one or more "weaving class loaders", either provided explicitly by the run-time environment or enabled through a "weaving agent" are required.
  • Run-time weaving, this is what actually Spring is doing. We define this as the weaving of classes that have already been defined. to the JVM
2
Chao Jiang On

Find a simple solustion for this question if you are using spring-boot:

In the jar, you can define your aspect as a component:

package com.xxx.yy.zz.aspect;
@Aspect
@Component
public class CoolAspect {
   // code like the question
}

And the, you need create a file spring.factories in /resources/META-INF/. Spring will scan this file when start.

And the file spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.xxx.yy.zz.aspect.CoolAspect

After that, just package them as a jar.

This will work by just declaring a Maven dependency