Java: Spring AOP & Refactoring

2020-07-23 04:12发布

问题:

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:

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:

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:

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:

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:

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. ;-)



标签: java spring aop