tags:

views:

421

answers:

3

I have a need for methods in several classes that must always follow a specific pre and post pattern.

public void method(X x, Y y ) {

// ********Repeating Part begin **************/

AFrameworkClass aFrameworkClass = new AFrameworkClass (this.memberVariable,"SomeString");

try {

  aFrameworkClass.aFrameworkMethod( x,y); 
  aFrameworkClass.anotherFrameworkMethod(x,y); 
  aFrameworkClass.yetAnotherFrameworkMethod(x);   
  aFrameworkClass.doPreProcessing(); 

  Throwable t = null ;

// ********Repeating Part End **************/

  try { 
     // code will vary according to the business logic 
  } 
  catch (Throwable t) { 
     // code will vary according to the business logic   
  }

// ********Repeating Part begin **************/

  aFrameworkClass.doPostProcessing();

} finally { aFrameworkClass.doCleanup();

}

// ********Repeating Part End **************/

}

Is it possible to use Spring framework to accomplish the logic in the repeating parts in this method without having to code those lines over and over again in my various classes? If so how?

+2  A: 

Absolutely it can be done with Spring's AOP support. You can apply the first part as "before" advice and the 2nd as "after-finally" advice or you can apply both as "around" advice and programmatically invoke the target method like so:

methodInvocation.invoke(); // returns Object

If you want to declare your aspects in XML you can read about how to do it here:

http://static.springframework.org/spring/docs/2.5.x/reference/aop.html#aop-schema http://static.springframework.org/spring/docs/2.5.x/reference/aop.html#aop-schema-advice-before http://static.springframework.org/spring/docs/2.5.x/reference/aop.html#aop-schema-advice-after-finally http://static.springframework.org/spring/docs/2.5.x/reference/aop.html#aop-ataspectj-around-advice

Or if you want to do it with annotations there is info here:

http://static.springframework.org/spring/docs/2.5.x/reference/aop.html#aop-ataspectj

Personally I prefer doing it with XML since the behavior of the aspects can be altered without recompiling the application. Let's say you have a multi-module project where B depends A. A contains reusable advice and is using annotations for order, pointcuts, etc. If you need to change that behavior, you must rebuild A. If you are using XML in project B to configure the aspect from project A, no rebuild of A is needed.

My feeling is that advice is more reusable when you define the behavior in a class and how that behavior is applied in XML.

cliff.meyers
What *exactly* are you referring to by 'Personally I prefer doing it with XML since the behavior of the aspects can be altered without recompiling the application'?
krosenvold
There are annotations in the AspectJ API that allow you to define AOP behavior in your Java code:http://static.springframework.org/spring/docs/2.5.x/reference/aop.html#aop-ataspectjFor instance, you can specify advice order using @Order. I would rather use XML instead; easy to change, no compile
cliff.meyers
The XMl configuration file typically packaged inside a EAR or WAR. You would have to rebuild the project to repackage, which in turn introduces the need regression test
zkarthik
Better reason: it makes advice more reusable when you define the behavior in a class and how it's applied in XML. Especially for things like pointcuts or order, you will want to change that project-by-project and not "bake it" into your code.
cliff.meyers
Also: let's say you have a multi-module project where B depends A. A contains reusable advice and is using annotations for order, pointcuts, etc. If you need to change that behavior, you must rebuild A. If you are using XML in project B to configure the aspect from project A, no rebuild of A needed.
cliff.meyers
How do I pass parameters into the injected between advice? Also the call into the proceed method takes no method parameters. I would like to pass parameters into the proceed method call.
zkarthik
You don't pass arguments to invoke(). You need to call getArguments() on the MethodInvocation object and modify the returned array.http://aopalliance.sourceforge.net/doc/org/aopalliance/intercept/MethodInvocation.html
cliff.meyers
A: 

brd6644 is right, but one thing I've discovered is a problem with Spring AOP is that the advice/advisors cannot be applied to the properties as you are creating the object.

That is, say you have something like

<bean class="...ProxyBeanFactory">
    <property name="target">
        <bean class="myBean">
            <property name="username" value="helloKitty"/>
            <property name="password" value="lkajdahdkahjdkhja"/>
        </bean>
     </property>
 </bean>

It is not possible to write an advisor to decrypt the password for myBean, since the property value is being supplied before the proxy is created. You can't apply the password property to the ProxyBeanFactory class, of course. What you really want to do is have setPassword() called on the object returned from the ProxyBeanFactory with the "lkaj..." argument, but that's not possible, it would seem.

nsayer
You make a "crypto" PropertyPlaceholderConfigurer to do this. I believe this is actually a sample in the spring reference under PropertyPlaceholderConfigurer
krosenvold
+1  A: 

As an alternative to a full-fledged IoC container, you can achieve the same thing using a delegate. Design a base class with the pre- and post- functions and a delegate to inject your varying business logic function. A "RunProcess" base class function would call the pre- operations, the delegate, then the post- operations.

Dave Swersky
Ah, this pattern appears simpler to understand than using a IoC framework. I will try this.
zkarthik