Explain Aspect-Oriented Programming
Dependency Injection goes a long way towards delivering the ideal of a fully featured application framework enabling a POJO programming model. However, configuration management isn't the only issue; you also need to provide declarative services to objects. It''s a great start to be able to configure POJOs-even with a rich network of collaborators-without constraint their design; it's equally important to be able to apply services such as transaction management to POJOs without them needing to implement special APIs.
The ideal solution is Aspect-Oriented Programming (AOP).
AOP provides a different way of thinking about code structure, compared to OOP or procedural programming. Whereas in OOP you model real-world objects or concepts, such as bank accounts, as objects, and organize those objects in hierarchies, AOP enables you to think about concerns or aspects in your system. Typical concerns are transaction management, logging, or failure monitoring. For example, transaction management applies to operations on bank accounts, but also to many other things besides. Transaction management applies to sets of methods without much relationship to the object hierarchy. This can be hard to capture in traditional OOP. Typically you end up with a choice of trade offs:
In short, with a traditional OO approach the choices are code duplication, loss of strong typing, or an intrusive special-purpose framework.AOP enables you to capture the cross-cutting code in modules such as interceptors that can be applied declarative wherever the concern they express applies — without imposing trade offs on the objects benefiting from the services. Spring AOP is used in the framework itself for a variety of purposes, many of which are behind the scenes and which many users may not realize are the result of AOP:
- Writing boilerplate code to apply the services to every method that requires them: Like all cut-and-paste approaches, this is unmaintainable; if you need to modify how a service is delivered, you need to change multiple blocks of code, and OOP alone can't help you modularize that code. Furthermore, each additional concern will result in its own boilerplate code, threatening to obscure the business purpose of each method. You can use the Decorator design pattern to keep the new code distinct, but there will still be a lot of code duplication. In a minority of cases the Observer design pattern is sufficient, but it doesn''t offer strong typing, and you must build in support for the pattern by making your objects observable.
- Retype operations, through something like the Command pattern: This enables a custom interceptor chain to apply behavior such as declarative transaction management, but at the loss of strong typing and readability.
- Choosing a heavyweight dedicated framework such as EJB that can deliver the necessary services: This works for some concerns such as transaction management, but fails if you need a custom service, or don't like the way in which the EJB specification approaches the particular concern. For example, you can't use EJB services if you have a web application that should ideally run in a web container, or in case of a standalone application with a Swing GUI. Such frameworks also place constraints on your code-you are no longer in the realm of POJOs.
- Declarative transaction management: This is the most important out-of-the-box service supplied with Spring. It''''s analogous to the value proposition of EJB container-managed transactions (CMT) with the following big advantages:
- It can be applied to any POJO.
- It isn''t tied to JTA, but can work with a variety of underlying transaction APIs (including JTA). Thus it can work in a web container or standalone application using a single database, and doesn''t require a full J2EE application server.
- It supports additional semantics that minimize the need to depend on a proprietary transaction API to force rollback.
- Hot swapping: An AOP proxy can be used to provide a layer of indirection. (Remember the discussion of how indirection can provide a key benefit in implementing Dependency Injection?) For example, if an Order Processor depends on an Inventory Manager, and the Inventory Manager is set as a property of the Order Processor, it''''s possible to introduce a proxy to ensure that the Inventory Manager instance can be changed without invalidating the Order Processor reference. This mechanism is thread safe, providing powerful "hot swap" capabilities. Full-blown AOP isn''t the only way to do this, but if a proxy is to be introduced at all, enabling the full power of Spring AOP makes sense.
- "Dynamic object" support: As with hot swapping, the use of an AOP proxy can enable "dynamic" objects such as objects sourced from scripts in a language such as Groovy or Beanshell to support reload (changing the underlying instance) and (using introduction) implement additional interfaces allowing state to be queried and manipulated (last refresh, forcible refresh, and so on).
- Security: Acegi Security for Spring is an associated framework that uses Spring AOP to deliver a sophisticated declarative security model.
There's also a compelling value proposition in using AOP in application code, and Spring provides a flexible, extensible framework for doing so. AOP is often used in applications to handle aspects such as:
- Auditing: Applying a consistent auditing policy — for example, to updates on persistent objects.
- Exception handling: Applying a consistent exception handling policy, such as emailing an administrator in the event of a particular set of exceptions being thrown by a business object.
- Caching: An aspect can maintain a cache transparent to peroxided objects and their callers, providing a simple means of optimization.
- Retrying: Attempting transparent recovery: for example, in the event of a failed remote invocation.