View Full Version : before and after advices in a single class?
venuko
Jul 11th, 2005, 07:10 PM
I created a class that implements both before and after advices:
public class SimpleTracer implements AfterReturningAdvice, MethodBeforeAdvice {...}
However when I register it as an interceptor with ProxyFactoryBean, it only functions as before advice. Am I doing something wrong?
markstgodard
Jul 11th, 2005, 09:26 PM
Can you post some config examples and / or any relevant log messages?
Andreas Senft
Jul 12th, 2005, 06:04 AM
I think this is conceptually problematic. If you need a before and an after part in the same type, why not using AroundAdvice?
Regards,
Andreas
venuko
Jul 12th, 2005, 12:22 PM
Can you post some config examples and / or any relevant log messages?
Relevant config fragments:
<bean id="enrollmentServiceImpl"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>
mypkg.IEnrollmentService
</value>
</property>
<property name="target">
<bean
class="mypkg.MockupEnrollmentServiceImpl" />
</property>
<property name="interceptorNames">
<list>
<value>tracer</value>
</list>
</property>
</bean>
<bean id="tracer"
class="org.springframework.aop.support.RegexpMethodPointc utAdvisor">
<property name="advice">
<bean class="mypkg.SimpleTracer" />
</property>
<property name="pattern">
<value>.*</value>
</property>
</bean>
Log messages:
12-Jul-2005 10:06:02 AM org.springframework.beans.factory.support.DefaultL istableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in factory [org.springframework.beans.factory.support.Default ListableBeanFactory defining beans [enrollmentServiceImpl,tracer]; root of BeanFactory hierarchy]
12-Jul-2005 10:06:02 AM org.springframework.beans.factory.support.Abstract BeanFactory getBean
INFO: Creating shared instance of singleton bean 'enrollmentServiceImpl'
12-Jul-2005 10:06:02 AM org.springframework.aop.framework.DefaultAopProxyF actory <clinit>
INFO: CGLIB2 not available: proxyTargetClass feature disabled
12-Jul-2005 10:06:02 AM org.springframework.beans.factory.support.Abstract BeanFactory getBean
INFO: Creating shared instance of singleton bean 'tracer'
The advisor bean:
package mypkg;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
public class SimpleTracer implements AfterReturningAdvice, MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("in ---> " + method.getName());
}
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("out <--- " + method.getName());
}
}
When I invoke a method on the enrollmentServiceImpl bean, only the "before" method of the SimpleTracer gets invoked.
venuko
Jul 12th, 2005, 12:28 PM
I think this is conceptually problematic. If you need a before and an after part in the same type, why not using AroundAdvice?
It seems to me that AroundAdvice is more appropriate when there is a need to control the method invocation.
katentim
Jul 12th, 2005, 07:39 PM
When I invoke a method on the enrollmentServiceImpl bean, only the "before" method of the SimpleTracer gets invoked...Am I doing something wrong?
It appears you can only have one advice type per class. Spring retrieves an advisor in this order: Interceptor, BeforeAdvice, AfterAdvice and then ThrowsAdvice (see DefaultAdvisorAdapterRegistry.getInterceptor(..)). So if you define BeforeAdvice and AfterAdvice, Spring will only use the BeforeAdvice advice.
It seems to me that AroundAdvice is more appropriate when there is a need to control the method invocation.
Around advice is needed if you need to change the object returned. It's also slightly more risky, because it is up to the developer to invoke the target and return the object. You could also just consider using separate Before and After advice (in different classes).
Andreas Senft
Jul 13th, 2005, 12:58 AM
Around advice is needed if you need to change the object returned.
That is true, but that does not mean that you cannot use it in other cases as well (no one forces you to change the return object in an around advice :) ). If I want to perform code before and after an invocation I find it to be a good choice. Afaik some interceptors provided by Spring use also AroundAdvice (i.e. MethodInterceptor) without toying around with the return value.
It's also slightly more risky, because it is up to the developer to invoke the target and return the object.
I agree. But you are the developer and you should know what you are doing :P
You could also just consider using separate Before and After advice (in different classes).
If the before code has nothing to do with the after code that is perfectly legal, leveraging reusability. Otherwise I would refrain from artificial distinctions.
Another option is, to provide an abstract MethodInterceptor implementation that does the proceed invocation and provides callback hooks before and afterwards (using the template method pattern).
Regards,
Andreas
katentim
Jul 13th, 2005, 01:24 AM
But you are the developer and you should know what you are doing
Agreed. Just providing the word of warning.
robh
Jul 13th, 2005, 03:07 PM
All,
I committed a fix for this into CVS today and it has been scheduled for release in 1.2.3.
Regards,
Rob
katentim
Jul 13th, 2005, 04:42 PM
I committed a fix for this into CVS today
Cheers - beat me to it. I think this is the best solution.
Powered by vBulletin® Version 4.2.1 Copyright © 2013 vBulletin Solutions, Inc. All rights reserved.