Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AspectJ - Weaving with custom ClassLoader at runtime

I'm trying to load classes at runtime and weave them with some AspectJ aspects at this point. I have load-time weaving enabled, and it works when I use it more conventionally.

I have the following in my @Aspect class:

@Before("call(* mypackage.MyInterface.*())")
public void myInterfaceExecuteCall(JoinPoint thisJoinPoint,
        JoinPoint.StaticPart thisJoinPointStaticPart,
        JoinPoint.EnclosingStaticPart thisEnclosingJoinPointStaticPart) {
    System.out.println(thisJoinPoint.getSignature().getDeclaringType());
    System.out.println(thisJoinPoint.getSignature().getName());
}

Then I'm scanning the jars and finding classes that are implementations of MyInterface:

URLClassLoader classLoader = new URLClassLoader(new URL[] { urlOfJar },
        ClassLoader.getSystemClassLoader());
WeavingURLClassLoader weaver = new WeavingURLClassLoader(
        classLoader);
HashSet<Class<?>> executableClasses = new HashSet<Class<?>>();
for (String name : classNamesInJar) {
    try {
        Class<?> myImplementation = weaver.loadClass(name);
        if (MyInterface.class.isAssignableFrom(myImplementation)) {
            executableClasses.add(myImplementation);
        }
    } catch (Exception e) {
        e.printStackTrace();
    } catch (NoClassDefFoundError e) {
        e.printStackTrace();
    }
}

... and then I'm executing a specific method in the loaded classes at some point:

try {
    Method execute = myImplementation.getMethod("execute");
    execute.invoke(myImplementation.newInstance());
} catch (Exception e) {
    e.printStackTrace();
}

However, the @Before method that I gave you above is never executed when I call execute.invoke(...) (although the execute method itself is obviously executed, since I see its output).

Does someone know what I'm doing wrong? What's the way to make myInterfaceExecuteCall get called before the loaded class's methods get called?

like image 213
Hinton Avatar asked May 24 '12 07:05

Hinton


People also ask

What is runtime weaving?

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.

What is weaving in AspectJ?

Weaving in AspectJ Classes are defined using Java syntax. The weaving process consists of executing the aspect advice to produce only a set of generated classes that have the aspect implementation code woven into it.

How does AspectJ works?

What AspectJ does is always pretty much the same: It modifies Java byte code by weaving aspect code into it. In case 1 you just get one set of class files directly from ajc . Case 2.1 creates additional, new class files. Case 2.2 just creates new byte code in memory directly in the JVM.

Why AspectJ is used?

AspectJ Provides a Standard Mechanism to Handle a Crosscutting Concern. In the example shown above, we are doing a null validation and throwing an IllegalArgumentException when the request is null. This way we make sure that whenever an argument is null, we get the same uniform behavior.


1 Answers

OK I found out what it was, and it doesn't work quite the way I intended it, but here is a workaround:

Just do a @Before("execution(* mypackage.MyInterface.*())") instead of call. This works even if the class was loaded manually and at runtime by a custom class loader. This is because AspectJ doesn't care about calls that are done with using Method.invoke(...). I hope someone else can use this workaround.

Here is a link to the documentation containing the memorable info:

For example, the call pointcut does not pick out reflective calls to a method implemented in java.lang.reflect.Method.invoke(Object, Object[]).

http://www.eclipse.org/aspectj/doc/released/progguide/implementation.html

If you have a different solution, please don't hesitate to answer!

like image 167
Hinton Avatar answered Sep 28 '22 04:09

Hinton