我正在尝试使用Spring AOP来分析我的控制器,但是一旦我在我的servlet上下文xml中启用了monitoringAdvisor,我的@Controller类构造函数就会被下面提到的堆栈调用两次。
我认为它与CGLIB代理有关,它来自@Controller注释类(在本例中为PersonController)
但如果是这样的话那就不是针对Spring的Singleton概念(假设我尝试在单例中获取系统范围的资源)。 请告诉我如何在使用CGLIB代理时避免此问题。
我没有在web.xml中使用任何ContextLoaderListener,
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代码
@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) {
}
}
当org.mypackage.PersonController(使用@Controller注释的类)构造函数首先命中时调用堆栈
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
断点点击第二次时调用堆栈
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
答案 0 :(得分:1)
在http://nurkiewicz.blogspot.in/2011/10/spring-pitfalls-proxying.html找到答案 以下段落
“而不是子类化和实例化子类bean Spring首先创建原始bean,然后在其中一个后处理器中创建一个包装原始(有点装饰模式)的子类”
这就是为什么构造函数被调用两次,但实际上只有一个bean。我试过@PostConstruct,这只被叫了一次,这澄清了我的所有怀疑。所以基本上只有一个bean。另一个只是代理人。