Spring AOP injecting a 'silent' method parameter
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 */);
}