Spring AOP injecting a 'silent' method parameter

Spring AOP injecting a 'silent' method parameter
java
Ethan Jackson

I'm pretty sure it's not possible to achieve this strange behaviour, but going to throw it out there ..

I want to inject a method parameter and have it available to the method code. However I do not want it in the parameter list.

My current implementation is I have written an Aspect which searches for a Transaction object in the parameter list, creates and starts that transaction, injects it in the right place in the args[], proceeds(args) and then commits or rolls back. I can't use spring transactions because it's a global transaction which manages two underlying resources which do not support XA transactions and I don't want have this custom transaction management boiler plate code pasted into every method.

e.g. pseudocode of how it would be applied

@MyTransaction public void myMethod (String user, Transaction tx, String otherParam) { mySPecialAdapter.insert(createSomeCypherQL(user), tx); }

The problem is it looks weird from the calling site, like I have to pass something, even though I know under the hood it will be replaced by the correct Transaction object

myMethod("user", null, "otherParam");

Maybe I'm coming at it from the wrong angle..

Answer

Personally, I wouldn't use an aspect to do this. Mainly because there's no way to magically inject a parameter that isn't in the method signature. Secondly, those annotation-driven aspects will cause a lot of head scratching unless it's well documented in the java docs where the @#%@ the Transaction comes from.

This is what I would do.

First, extract the logic that resolves the Transaction from the aspect and place it into a Service

@Service public class TransactionService { public Transaction resolveTransaction( /* the args that are needed */ ) { ... return transaction; } }

Inject this service into the component that exposes myMethod

... @Autowired private TransactionService transactionService; // delegate to the service to resolve the Transaction public void myMethod (String user, String otherParam) { mySPecialAdapter.insert(createSomeCypherQL(user), transactionService.resolveTransaction(/* the args that are required */); }

Related Articles