Reputation: 870
I am trying to use Spring AOP for profiling my Controllers, but as soon as I enable monitoringAdvisor in my servlet context xml my @Controller class constructor gets called twice with below mentioned stacks.
I assume it has something to do with CGLIB proxy which derives from by @Controller annotated class (PersonController in this case)
But if that's the case then isn't this against the Singleton concept of Spring (suppose I try to acquire a system wide resource in the singleton). Please let me know how can I avoid this problem when using CGLIB proxying.
I am not using any ContextLoaderListener in web.xml,
my-servlet.xml
<bean id="monitoringInterceptor" class="org.javasimon.spring.MonitoringInterceptor" />
<bean id="monitoringAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="monitoringInterceptor" />
<property name="pointcut">
<bean class="org.javasimon.spring.MonitoredMeasuringPointcut" />
</property>
</bean>
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
</bean>
<context:component-scan base-package="org.mypackage" />
Java code
@Controller
public class PersonController {
PersonController()
{
}
@Monitored // works well even when I remove this annotation
@RequestMapping(value="/addPerson", method=RequestMethod.POST)
public String addPerson(HttpServletRequest request) {
}
}
Call stack when the org.mypackage.PersonController (class annotated with @Controller) constructor hit first
PersonController.<init>() line: 48
NativeConstructorAccessorImpl.newInstance0(Constructor, Object[]) line: not available [native method]
NativeConstructorAccessorImpl.newInstance(Object[]) line: 57
DelegatingConstructorAccessorImpl.newInstance(Object[]) line: 45
Constructor<T>.newInstance(Object...) line: 526
BeanUtils.instantiateClass(Constructor<T>, Object...) line: 148
CglibSubclassingInstantiationStrategy(SimpleInstantiationStrategy).instantiate(RootBeanDefinition, String, BeanFactory) line: 87
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).instantiateBean(String, RootBeanDefinition) line: 1000
Call stack when the breakpoint hits second time
PersonController$$EnhancerByCGLIB$$4ad0c197(PersonController).<init>() line: 48
PersonController$$EnhancerByCGLIB$$4ad0c197.<init>() line: not available
NativeConstructorAccessorImpl.newInstance0(Constructor, Object[]) line: not available [native method]
NativeConstructorAccessorImpl.newInstance(Object[]) line: 57
DelegatingConstructorAccessorImpl.newInstance(Object[]) line: 45
Constructor<T>.newInstance(Object...) line: 526
ReflectUtils.newInstance(Constructor, Object[]) line: 228
ReflectUtils.newInstance(Class, Class[], Object[]) line: 220
ReflectUtils.newInstance(Class) line: 216
Enhancer.createUsingReflection(Class) line: 643
Enhancer.firstInstance(Class) line: 538
Enhancer(AbstractClassGenerator).create(Object) line: 225
Enhancer.createHelper() line: 377
Enhancer.create() line: 285
CglibAopProxy.getProxy(ClassLoader) line: 205
Upvotes: 1
Views: 1230
Reputation: 870
Found the answer at http://nurkiewicz.blogspot.in/2011/10/spring-pitfalls-proxying.html following paragraph
"Instead of subclassing and instantiating subclassed bean Spring first creates the original bean and then creates a subclass which wraps the original one (somewhat Decorator pattern) in one of the post processors"
Thats why the constructor is getting called twice, But there is actually one bean only. I tried @PostConstruct and that got called just once, which clarified my all doubts. So essentially there is only one bean. the other one is just a proxy.
Upvotes: 1