Even if you're not a big fan of Aspect-Oriented Programming, if you use the Spring framework's transaction management your application will be using dynamic AOP proxies, albeit behind-the-scenes. Spring can use two
different techniques for creating proxies at runtime: CGLIB or JDK dynamic proxies.
If the target class implements one or more interfaces, then Spring will create a JDK dynamic proxy that implements every interface. If the target class implements no interfaces, Spring will use CGLIB to create a new class on the fly that is a subclass ("extends") the target class. This leads to one important difference: a JDK dynamic proxy cannot be casted to the original target class because it's simply a dynamic proxy that happens to implement the same interface(s) as the target. This has the effect of "nudging" you to program to interfaces if they're being used in your application's model, since proxies will usually be invoked through those interfaces.
On the other hand, if interfaces are completely absent from your model, Spring will create CGLIB proxies that can be treated more-or-less just like the target class itself. There is also a way to force creation of CGLIB proxies in either scenario that is detailed in the Spring docs right here.
If you're receiving strange ClassCastExceptions when working with your Spring-managed service layer, hopefully this tip will help you!