This action might not be possible to undo. Are you sure you want to continue?
The motivation of AOP is not to substitute for OOP. In fact, AOP is often used together with OOP. In the world of OOP, applications are organized with classes and interfaces. These elements are good for implementing the core business requirements, but not the crosscutting concerns (i.e., the functions or requirements that span multiple modules of an application). Crosscutting concerns are very common in enterprise applications. The typical examples include logging, validation, and transaction management. AOP provides another way for developers to organize their application structures. Instead of the classes and interfaces of OOP, the main programming elements of AOP are aspects. You may imagine that an aspect modularizes crosscutting concerns like a class modularizes states and behaviors in OOP. Besides the IoC container, another core module of the Spring framework is its AOP framework. Currently, there are many AOP frameworks on the market implemented for different purposes and based on different technologies, but only the following three open source AOP frameworks have entered the mainstream: • AspectJ, merged with AspectWerkz since version 5 (http://www.eclipse.org/aspectj/) • JBoss AOP, as a subproject of the JBoss application server (http://labs.jboss.com/ jbossaop/) • Spring AOP, as part of the Spring framework (http://www.springframework.org/) Among them, AspectJ is the most complete and popular AOP framework in the Java community. By comparison, Spring AOP is not a competitor of AspectJ to provide another complete AOP implementation. Its purpose is only to provide an AOP solution that can consistently integrate with its IoC container. In fact, Spring AOP will only handle crosscutting concerns for the beans declared in its IoC container. The core implementation technology of Spring AOP is dynamic proxy. By definition, a crosscutting concern is a functionality that spans multiple modules of an application. This kind of concern is often hard to modularize with the traditional objectoriented approach. To understand crosscutting concerns, let’s start with a simple calculator example. First, you create two interfaces, ArithmeticCalculator and UnitCalculator, for arithmetic calculation and measurement unit conversion.
Tracing the Methods
A common requirement of most applications is to trace the activities that take place during program execution. For the Java platform, there are several logging implementations available for you to choose. However, if you would like your application to be independent of the logging implementation, you can make use of the Apache Commons Logging library. It provides abstract APIs that are implementation independent and allows you to switch between different implementations without modifying your code.
Validating the Arguments
Now let’s consider adding a restriction to your calculators. Suppose you would like your calculators to support positive numbers only. At the beginning of each method, you make calls to the validate() method to check if all the arguments are positive numbers. For any negative numbers, you throw an IllegalArgumentException.
Identifying the Problems
As you can see, the original calculator methods expand as you add more and more nonbusiness requirements, such as logging and validation. These systemwide requirements usually have to crosscut multiple modules, so they are called crosscutting concerns to distinguish them from the core business requirements, which are called the core concerns of a system. Typical crosscutting concerns within an enterprise application include logging, validation, pooling, caching, authentication, and transaction. Figure 5-1 shows the crosscutting concerns in your calculator application. Figure
Like the preceding calculator methods. Figure 5-2 illustrates the general idea of the proxy design pattern. the preceding calculator implementations would be hard to reuse in another application that has no logging requirement and can accept negative numbers as operands. For the logging requirement.However. Another problem caused by non-modularized crosscutting concerns is code scattering. Developers often have to mix them with core concerns in the same modules. Any calls that were made to the original object will go through the proxy first. For instance. There are two main problems caused by non-modularized crosscutting concerns. Modularizing Crosscutting Concerns with Dynamic Proxy You can apply a design pattern called proxy to separate crosscutting concerns from core concerns. the calculators should concentrate on the core calculation logic only. Later. the traditional object-oriented approach cannot modularize crosscutting concerns well. with only classes and interfaces as programming elements. it is also hard to ensure that the logging requirement will be implemented consistently. Let’s separate the logging and validation concerns from them. you have to repeat the logging statements multiple times in multiple modules to fulfill a single requirement. if the logging criteria change. the overall system logging will be inconsistent. which belong to the “structural pattern” category. If you have missed a logging statement somewhere. As a result. This will lead to poor code maintainability and reusability. The principle of the proxy design pattern is to wrap an object with a proxy and use this proxy to substitute for the original object. these crosscutting concerns are spread out in different modules of an application and are thus not modularized. . Proxy is one of the 23 GoF (Gang of Four) object-oriented design patterns. For all these reasons. The first is code tangling. you would have to modify all of the modules. Moreover. each of them has to handle multiple concerns as well as the core calculation logic at the same time.
3 or higher. In Java. dynamic proxy is one of the core technologies used by Spring for its AOP implementation. you would like to seek another approach to modularize them. Static proxy works by wrapping an object with a dedicated proxy to performadditional tasks around each method call.The proxy object is responsible for deciding when and whether to forward method calls to the original object. and only the calls to the methods declared in the interfaces will go through the proxy. Dynamic proxies are implemented with the Java Reflection API. the proxy would be a good place to implement the crosscutting concerns. For example. Solution AOP defines a group of high-level concepts for application developers to express their crosscutting concerns. CGLIB proxy. First. each of which takes effect at different . so they can be used in a more general way than static proxies. there are two ways to implement the proxy design pattern. It can handle all the methods declared in a class even if it doesn’t implement any interface. The only restriction is that the object must implement at least one interface. the crosscutting action to take at a particular execution point is encapsulated in an advice. However. The dedication means you have to write a proxy class for each interface to be able to substitute for the original implementation. In the meanwhile. which is very inefficient in a large application with hundreds or thousands of components Another method is through the dynamic proxy support offered by JDK version 1. For this reason. Classic Spring AOP supports four types of advices. you can encapsulate the logging and validation actions in one or more advices. Modularizing Crosscutting Concerns with Classic Spring Advices Problem As crosscutting concerns are often hard to modularize with the traditional object-oriented approach. but it’s too demanding for an application developer to write such low-level proxy code. So. there’s another kind of proxy. that doesn’t have this restriction. the proxy can also perform additional tasks around each method call. The traditional one is to write a static proxy in pure object-oriented style. Dynamic proxy is helpful in modularizing crosscutting concerns. It supports creating a proxy dynamically for any object.
including method executions. the definition of the four classic advice types can be narrowed down to the following: • Before advice: Before the method execution • After returning advice: After the method returns a result • After throwing advice: After the method throws an exception • Around advice: Around the method execution When using the classic Spring AOP approach. In the formal AOP definition. . However. and field accesses. So.times of an execution point. constructor executions. there are many types of execution points. Spring AOP only supports method executions. advices are written by implementing one of the proprietary advice interfaces.
This action might not be possible to undo. Are you sure you want to continue?