Generically chain dynamic proxies

Add AOP concepts to your application

1 2 3 4 Page 4
Page 4 of 4

Previously I discussed using Class.forName and some of its implications. We cannot set any variable earlier to the target object/invocation handlers/interceptors using the Class.forName approach. Thus, for simplicity, I provided the method above (you can also use the same method in Approaches 1 and 2). Now you can pass an existing instance of the target object or invocation handlers/interceptors. For example, the code on the client side may look like the following:

 

MyDebugInvocationHandler dHandler = new MyDebugInvocationHandler(); MyAnotherInvocationHandler aHandler = new MyAnotherInvocationHandler(); IMyBusinessObject bo = new MyBusinessObject();

//Now set any variables to these objects //or some of these objects may be singletons

Object[] invocationHandlers = { dHandler, aHandler }; (IMyBusinessObject)MyProxyFactory.getProxyObject (bo , invocationHandlers); String ret = aIMyBusinessObject.doExecute("Hello World");

The class diagram of Approach 3 appears in Figure 4.

Figure 4. Generically chain dynamic proxies: Approach 3 class diagram

In addition to the approaches outlined in this article, several other variations exist. Specifically, the proxy factory can be written differently. Also, you can write the proxy factory such that it can mix and match Approaches 1 and 3.

A simple comparison among different approaches

I conducted a simple test to find out how much time each approach required for calling the actual business method after wrapping it with the interceptor. This test cannot be considered a scalability test since the machine configuration (like processor speed, number of processors, and available and used memory) was not considered. Still, from this simple test, we can get a rough idea about the performance of each approach.

To conduct the test, first, all the System.out.println statements were commented out (to ensure that I/O time wouldn't be a factor). Next, in each approach, the call to the business method using the proxy factory was called inside a loop that ran 1,000 times. On top of that, the same program was run 20 times. The following information shows the times in milliseconds for an average of 1,000 invocations (serially).

  • Static decorator chaining: 51.7 milliseconds for 1,000 invocations
  • Dynamic proxy chaining: Approach 1: 166.5 milliseconds for 1,000 invocations
  • Dynamic proxy chaining: Approach 2: 125.1 milliseconds for 1,000 invocations
  • Dynamic proxy chaining: Approach 3: 159.25 milliseconds for 1,000 invocations

Though the static decorator chaining requires the least amount of time, if we consider a single method invocation, the comparison comes down to a microsecond level, and that is not too much. And in practice, to gain some microseconds or milliseconds by rejecting a generic approach often results in a scattered approach with lots of custom coding, which essentially takes more execution time.

As mentioned earlier, we can mix and match Approaches 1 and 3 to build a good AOP framework. On the other hand, if we need specific cross-cutting aspects (all advantages cannot be achieved) to weave into our application, and we need to also consider performance in microseconds, then we can think about using Approach 2.

Conclusion

In this article's examples, the methods are static inside the factories. This approach can create future problems if you want to extend a factory or have multiple factory instances with different configurations. Hence, use the proper Factory pattern to write your factory.

I have only touched on some of the concepts of AOP, showing how to implement them using dynamic proxies in Java. Several other AOP concepts like join points (well-defined points in a program's execution, such as a method invocation or a specific exception being thrown), and point cuts (a set of join points) can also be implemented in your factory class. Please see Resources for more information.

If you need to use AOP concepts heavily throughout your application and can choose an existing framework, then choose a well-known, well-tested, and well-supported framework rather than build one yourself. If such a framework is not an option for you, consider building your own AOP framework. An AOP alliance has been formed that provides the interfaces for Java AOP to intercept method calls (see Resources for more information). Before building your own framework, look at the AOP alliance interfaces.

If you use an existing framework that does not provide AOP support and you need to implement a few AOP features, instead of introducing a full-blown AOP framework into the project, consider building a small framework on your own with generic dynamic proxies. Hopefully this article has provided some idea of how to achieve that. If you use an existing AOP framework that uses a dynamic proxy approach, then this article should help you understand the basics of dynamic proxies and their chaining.

Srijeeb Roy holds a bachelor's degree in computer science and engineering from Jadavpur University, Calcutta, India. He is currently working as a technical architect at Tata Consultancy Services Limited in a J2EE-based project. He has been working in Java/J2EE for more than 6 years and has total experience of 7.5 years in the IT industry. He has developed several in-house frameworks in Java for his company and clients. He has also worked in several other areas like Forte, CORBA, and J2ME.

Learn more about this topic

This story, "Generically chain dynamic proxies" was originally published by JavaWorld.

Copyright © 2006 IDG Communications, Inc.

1 2 3 4 Page 4
Page 4 of 4