3
votes

So I'm starting to get into Spring AOP, and something occurred to me. When configuring an aspect, the annotations all use Strings as parameters, rather than Class objects.

I bring this up because this means that an IDE (I use Eclipse, so I'll just refer to it here) won't be able to refactor the aspect properly. So if I have a class MyClass, with a method public void foo(), an example of a Spring AOP annotation would be this:

@Before ("execution(public void package.MyClass.foo())")

Because the param in the annotation is a String, if I refactored the method name to public void foo2(), it would break the binding of this aspect.

I've been scouring various forums and tutorials, but everywhere I look I just see String parameters, which suggests that's the only option here. I guess you could work around this by being a bit more generic in how you declare the binding:

@Before ("exeuction(public void package.MyClass.set*(..))")

This new one will work for any setter method in MyClass, with any number of parameters (or no params). Of course, being vague like this might not work all the time.

Anyway, I'm ranting a little bit here, it's late and I'm kind of tired and my brain is all worn out from hunting for an answer to this. But my final question is this: is there any way to set up Spring AOP annotations so that refactoring will affect them?

Thanks.

1
I'm not an expert, but I suspect that any answer is likely to be more about teaching Eclipse to handle this right, rather than being able to use AOP differently. I've taken the liberty of adding the "eclipse" tag.ajb
And it looks like someone else took the liberty of yanking it off. I have no idea why.ajb
Class.getMethod(String name, Class<?>... parameterTypes), for example, requires a String, but there's no way around that. That's probably what Spring uses. I agree that it would have to involve an Eclipse configuration.Lucas Ross
Basically this has nothing to do with Spring or Spring AOP. The @Before is an AspectJ annotation and NOT a spring annotation. This is rather about the tooling support for annotation driven aspects if you write real aspects (public aspect MyAspect instead of @Aspect public class MyAspect you get this support at least partially). The greater question is the IDE support instead of framework support.M. Deinum

1 Answers

4
votes

Well, the whole point of AOP is to implement cross-cutting behaviour in a modular way and apply it to application code which ideally is unaware of any aspects. Thus, you have no fixed connection between the two. It is just important to remember that as much as you maintain and refactor your application code, you should also refactor your aspects with it in oder to make sure that pointcuts do not break.

Having said that, Eclipse and other IDEs still give you hints about which aspects are applied where if you install AJDT (AspectJ Development Tools). I mainly use full AspectJ, not the proxy-based "AOP lite" variant called Spring AOP, so I do not know if AJDT is any useful with Spring AOP. It will be with AspectJ applied to Spring via LTW (load-time weaving), though.

Here is a screenshot from "Aspect Visualisation" perspective:

Aspect visualisation perspective in Eclipse

It graphically shows which aspects apply to which parts of the code. If you double-click any of the dotted lines, a code editor will lead you to the exact place where an aspect is applied.

There also is the cross-reference view with little indicators within aspect code as well as plain Java code:

AJDT cross-reference view in Eclipse, part 1

On the right hand side there is the cross-reference view listing all aspects applying to the currently selected method. On the left hand side there are little icons indicating which types of advice apply to each method.

BTW, the cross-reference view also works from aspects. When you place the cursor to within an advice, the xref view lists all places in the code where the advice applies:

AJDT cross-reference view in Eclipse, part 2

There is more: The AspectJ compiler can be configured in such a way so as to list all joinpoints advised by aspect code. You can check the output for changes manually or even in an automated smoke test. For instance, if an advice does not apply anymore because you changed some package, class or method names, there will be an Xlint warning "adviceDidNotMatch" and/or sometimes also "invalidAbsoluteTypeName". Furthermore, the cross-reference view for the advice in question will be empty:

AspectJ compiler warnings

As you have just seen, there are plenty indicators and helpers within AJDT when refactoring application or aspect code.

One more thing: If you use AspectJ instead of Spring AOP you have an option to use the more concise and expressive native AspectJ syntax instead of the annotation-style syntax. I definitely prefer the former to the latter. Then you have more than just strings in your code editor, better syntax highlighting and code completion and refactoring.

Last, but not least: You should also write unit and maybe integration tests for your aspect code so as to notice if aspects break. Manual checks are nice, but automated regression tests are unbeatable when it comes to immediate feedback. ;-)