As someone who has spent days trying to find where the bloody hell a transaction is being created (with @Transactional) I can whole heartedly agree with this. If you have to explicitly pass a transaction context around, it rapidly becomes an obvious code smell if you're passing it to too many places. The way I found where the transaction was being created was to insert logging into the jdbc layer, I simply couldn't work it out from the annotations. Turns out there wasn't a transaction at the place where it was needed, but at pretty much every method below that. So one call to one web service caused ~1000 transactions.
And while we're on the subject, talking about @Autowired - we had one bean which had ~50 autowired dependencies. They didn't have any unit tests for this class surprisingly. Again, this would have been obvious if we'd had to use constructor injection. I find @Autowired really really useful, but on big systems it becomes really unwieldy.
Matthew Farwell.