Spring AOP injecting a 'silent' method parameter

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 */);
}
© 2024 Dagalaxy. All rights reserved.