Honestly, I think some of the best uses for AOP can be found in the Spring framework projects themselves!
- automatically proxying calls to objects to expose JMX methods and attributes (killer feature for monitoring and so on)
- automatically map objects to other APIs based on the presence of your own custom annotations. You see this in Spring MVC, Spring integration, the Spring support in the Activiti project, Spring Data Jpa, Spring Hadoop, Spring Batch, Spring WS, etc, where the annotations tell Spring which beans it should proxy to apply things like HTTP request dispatching, etc)
- ReflectionUtils and ProxyFactoryBean are your friends, btw ;-)
- AOP's used to handle API design in a clean way. One example in the Spring framework is the LocalEntityManagerFactoryBean, wihch helps provide an EntityManager to clients that want it. However, once injected that bean is not (usually, unless scoped) re-injected, which means that the object has to be thread-safe in the face of concurrent access. AOP allows you to get a proxied object which in turn delegates to a real EntityManager, but maintains (basically) a threadlocal map of requests so that - effectively, each thread gets its own EntityManager for each request. To the user, it's just one object, though. It makes the resource - which is not thread safe - threadsafe, while not requiring developers to do things like synchronize access on the class variable. In the Spring support in the Activiti project, there's support for access process variables from the current business process scope. Again, here you inject a variable, but the variable is bound to the scope, so it's actually a different value for different threads.
- AOP provides support for things like mixins - you can actually build a single object that exposes several interfaces and delegates to individual implementations.
- there are other niceties like an factory bean that - using AOP - automatically factories any resource, but makes it thread local to a given client, growing the pool as required.
Basically, AOP is a very powerful technology for implementing framework-type stuff. AOP has some great, well defined, immediately useful use cases like declarative transactions, logging, caching (in Spring 3.1), security, etc., but to me its real power is in being able to meet framework challenges when there's no existing solution at hand. (It doesn't matter how good a technology is, it'll never be perfect, so it's nice to know that Spring has your back here, as well)