I've been a zone leader with DZone since 2008, and I'm crazy about community. Every day I get to work with the best that JavaScript, HTML5, Android and iOS has to offer, creating apps that truly make at difference, as principal front-end architect at Avego. James is a DZone Zone Leader and has posted 639 posts at DZone. You can read more from them at their website. View Full User Profile

A Tour of AOP

09.12.2008
| 27092 views |
  • submit to reddit


DECORATOR AND PROXY

The decorator and proxy design pattern use a wrapper object that can perform some work before, after, or around invocation of the wrapped object or its representation. This additional work can be crosscutting in nature. For example, each method may perform a security check before the wrapped object’s method is invoked.

Figure 4: The decorator design pattern. The original object is wrapped in the decorator that presents the same interface as the decorated object. Each method passes through the decoration, which can implement functionality such as security and transactionFigure 4: The decorator design pattern. The original object is wrapped in the decorator that presents the same interface as the decorated object. Each method passes through the decoration, which can implement functionality such as security and transaction

A direct use of decorator and proxy design patterns for crosscutting concerns implementation require substantial effort. However, these patterns may be used as the underlying implementation technique as a part of an AOP system. The Spring Framework makes use of the proxy design pattern internally to avoid exposing the pattern to the users. This isn’t unlike the byte-code manipulation technique—cumbersome as a programming technique to deal with crosscutting concerns, but a perfectly fine underlying technology to implement AOP systems.

Another design pattern, interceptor, is often used along with the proxy design pattern. Let’s compare how it stands up against AOP for crosscutting concerns.

INTERCEPTOR

The interceptor pattern allows expressing crosscutting logic into an interceptor object. By attaching the interceptor to specific program elements, you can have the interceptor logic invoked around the intercepted elements. This pattern when used along with the proxy or decorator design pattern offers a reasonable solution for a wide range of crosscutting problems. For example, Java supports creation of dynamic proxies, which can be configured with an interceptor. Implementing the interceptor pattern generically and successfully requires a fair amount of machinery and thus is best left to a framework.

Let’s consider the newest implementation of the interceptor pattern in EJB3. The earlier versions of the EJB framework offered a solution for a specific set of crosscutting concerns: transaction management and role-based security, primarily. EJB3 offers a way to modularize user-specific crosscutting concerns through the interceptor approach.

public class TracingInterceptor {
private Logger logger = ...
@AroundInvoke
public Object trace(InvocationContext context) throws Exception {
logger.log("Entering " + context.getMethod().getName()
+ " in " + context.getBean().getClass().getName());
return context.proceed();
}
}

Then you can apply the interceptor to target classes and methods as shown in the following code snippet:

@Stateless
@Interceptors({TracingInterceptor.class})
public class InventoryManagementBean {
...
}

You can target specific methods by marking each such method with the @Interceptors annotation. On the other extreme, you can declare an interceptor as a default interceptor, which applies to all beans, except those that opt-out. EJB3’s implementation has a few limitations, such as an interceptor may be applied only to EJBs and not to ordinary types in the system, which may pose restrictions on certain usages. The programming model is also a bit complex and type-unsafe as access to the intercepted context (intercepted bean, method name, method arguments) are accessed through the InvocationContext object whose method returns Object and may require casting before using.

However, the real problem with the EJB interceptor design (and many other similar interceptor implementations) is the missing key abstraction of pointcuts. Instead of declaring classes and methods that need to be intercepted, classes and methods need to declare that they need to be intercepted, reducing it to a more macro-like usage. As a result, while the logic equivalent to AOP’s advice is modularized, the pointcut equivalent logic is spread in all intercepted types. Further, due to generic nature of join point context, the interceptor method may need complex logic to pluck arguments from the correct place.

Note that the Spring framework, in versions prior to 2.0, used a mechanism similar to InvocationContext thus suffering from programming complexities similar to EJB3 interceptors. However, Spring’s AOP always used a notion of pointcut to avoid the problem of spreading selection logic in multiple places. Furthermore, the AspectJ integration introduced in Spring 2.0 removes the need for InvocationContext-like logic and raises the pointcut implementation to a new level.