1

I'm trying to use Spring to provide load time weaving to several classes in a project I've created. I'm having trouble getting it to work when I call a class that is not within my local project.

I created a class named ExampleClass and when I perform an @Around on a method in there, I can see the modifications I made to the return, however when I attempt to do the same to String I'm unable to get any results.

This is my Aspect Code:

@Pointcut("call(* java.lang.String.*(..))")
public void cutString() {}

@Before("cutString()")
public void aroundString() throws Throwable {
    System.out.println("I Never See This");
}

Here's my call to that code:

public class Main {
    public static void main(String[] args) {
        new ClassPathXmlApplicationContext("classpath:my-context.xml");

        String string = new String("I Only See This");
        System.out.println(string.toLowerCase());
    }
}

The content of my-context.xml is just a <context:load-time-weaver />.

I have an aop.xml defined which as I said works for one class, but not another:

<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
    <weaver>
        <include within="com.example.*" />
        <include within="java.lang.String" />
    </weaver>

    <aspects>
        <aspect name="com.example.PerformMonitor" />
    </aspects>
</aspectj>

Am I missing something, or is this a limitation of Spring and AspectJ?

Nicholas
  • 7,403
  • 10
  • 48
  • 76

2 Answers2

3

Per default aspectj will not weave any java standard classes. This is a limitation to prevent security leaks as far as i remember. It is described in the aspectj documentation. Probably there is a property which allows changing this behavior but you should be very sure you need this before you start doing that.

Just create another jar with one class of your own and try to weave this one. This should work out of the box.

Martin Frey
  • 10,025
  • 4
  • 25
  • 30
2

Martin Frey is right. There are ways to weave JDK classes (I have done it), but it is a bit tricky and not for newbies - and mostly not necessary. Your alternative is to intercept the calls to, not the execution of your external methods. This way you do not need to weave into them. Clean and easy. Just use call() instead execution() for your external classes.

kriegaex
  • 63,017
  • 15
  • 111
  • 202
  • So if I did my point cut as `@Pointcut("call(* java.lang.String.*(..))")` this should allow me to intercept the method calls on `String`? I try this and it still does not hit my point. – Nicholas Apr 10 '13 at 15:06
  • Yes, it should - provided you control the callee so you can weave code into it. You cannot intercept calls to String methods from third-party libraries, unless you also weave your aspects into them via load-time weaving or binary weaving, creating newly woven versions and re-packaging them into JARs replacing the original ones. You have many options. – kriegaex Apr 10 '13 at 18:14
  • I have configured that pointcut, and I'm controlling the call to `string.toLowerCase()` and I'm calling my pointcut from an `@Before` and I cannot see my `System.out.println()` print out what I want. – Nicholas Apr 10 '13 at 18:17
  • Then probably your LTW configuration or your Spring configuration are wrong. [Update:] Caveat: Make sure you really use full AspectJ, not just Spring AOP which only works for Spring beans!!! – kriegaex Apr 10 '13 at 18:18
  • My above `AOP.xml` is what I have set, does that look correct? – Nicholas Apr 10 '13 at 18:20
  • I am sorry to say I am nowhere near a PC tonight, just answering from my iPad. I do not use LTW much, got to check it from my IDE next time I am in office. – kriegaex Apr 10 '13 at 18:23
  • Thank you for your help. I'll keep digging but and let comment if I get it, but any help would be appreciated. – Nicholas Apr 10 '13 at 18:24
  • I got it working by not having the `new ClassPathXmlApplicationContext("classpath:my-context.xml");`. – Nicholas Apr 11 '13 at 16:33
  • I am still on the road. Well, in order to use AspectJ you do not need Spring. Spring has its own AOP-style extension. Probably your configuration somehow tried to use that one. – kriegaex Apr 11 '13 at 18:47