[英]Can't autowired field in interceptor
当我将对象存储在数据库中时,我需要确定事件。 我使用拦截器方法。 拦截器类如下所示:
public class TaskInterceptor extends EmptyInterceptor {
@Autowired
private TaskNoticeRepository taskNoticeRepository;// my repository class
@Transactional
@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
return super.onSave(entity, id, state, propertyNames, types);
}
}
Spring 配置文件如下所示:
...<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="nestedTransactionAllowed" value="true"/>
</bean>
<bean id="taskInterceptor" class="ru.librait.cs.infrastructure.service.interceptor.crm.TaskInterceptor"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="ru.librait.cs.model,ru.librait.cs.infrastructure.dto.export"/>
<property name="entityInterceptor" ref="taskInterceptor" />...
当我构建项目时出现错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'actionController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ru.librait.cs.infrastructure.service.page.ActionPageService ru.librait.cs.controller.ActionController.actionPageService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'actionPageService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ru.librait.cs.model.repository.ActionRepository ru.librait.cs.infrastructure.service.page.impl.ActionPageServiceImpl.actionRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'actionRepository': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: protected org.hibernate.SessionFactory ru.librait.cs.model.repository.persistent.BaseRepositoryHibernate.sessionFactory; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/app.xml]: Cannot resolve reference to bean 'taskInterceptor' while setting bean property 'entityInterceptor'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'taskInterceptor': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ru.librait.cs.model.repository.crm.TaskNoticeRepository ru.librait.cs.infrastructure.service.interceptor.crm.TaskInterceptor.taskNoticeRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'taskNoticeRepository': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: protected org.hibernate.SessionFactory ru.librait.cs.model.repository.persistent.BaseRepositoryHibernate.sessionFactory; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'sessionFactory': FactoryBean which is currently in creation returned null from getObject
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:609)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:469)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:383)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:283)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4973)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5467)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:632)
at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1740)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:301)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:618)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:565)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:301)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1487)
at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:97)
at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1328)
at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1420)
at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:848)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:322)
at sun.rmi.transport.Transport$1.run(Transport.java:177)
at sun.rmi.transport.Transport$1.run(Transport.java:174)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:556)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:811)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:670)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ru.librait.cs.infrastructure.service.page.ActionPageService ru.librait.cs.controller.ActionController.actionPageService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'actionPageService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ru.librait.cs.model.repository.ActionRepository ru.librait.cs.infrastructure.service.page.impl.ActionPageServiceImpl.actionRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'actionRepository': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: protected org.hibernate.SessionFactory ru.librait.cs.model.repository.persistent.BaseRepositoryHibernate.sessionFactory; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/app.xml]: Cannot resolve reference to bean 'taskInterceptor' while setting bean property 'entityInterceptor'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'taskInterceptor': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ru.librait.cs.model.repository.crm.TaskNoticeRepository ru.librait.cs.infrastructure.service.interceptor.crm.TaskInterceptor.taskNoticeRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'taskNoticeRepository': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: protected org.hibernate.SessionFactory ru.librait.cs.model.repository.persistent.BaseRepositoryHibernate.sessionFactory; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'sessionFactory': FactoryBean which is currently in creation returned null from getObject
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:506)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284)
... 56 more
我该如何解决?
您创建了一个 hen-egg 配置(或循环依赖项):要创建sessionFactory
,您需要拦截器。 拦截器需要 repo。 回购需要sessionFactory
。
最简单的解决方法是注入ApplicationContext
并添加@PostConstruct
方法:
@Autowired
private ApplicationContext applicationContext;
private TaskNoticeRepository taskNoticeRepository;
@PostConstruct
public void init() {
taskNoticeRepository = applicationContext.getBean(TaskNoticeRepository.class);
}
这将这个设置向前移动了一点,并且经常起作用,但它很脆弱。
对于这样的事情,我更喜欢在应用程序启动时(在main()
或 servlet 上下文侦听器中)使用我从应用程序上下文中获取的“init beans”,它在创建所有 bean 之后但在任何“正常”之前连接这些依赖项" 代码有机会运行。
所以会有一个懒惰的 init bean,它依赖于拦截器和 repo。 拦截器会得到一个 repo 的 setter。 bean 将有一个公共的init()
方法来调用 setter。
这避免了各种可能有效也可能无效的“魔法”设置代码。
问题是循环依赖,设计不好..但你可以试试
<bean id="taskInterceptor" class="ru.librait.cs.infrastructure.service.interceptor.crm.TaskInterceptor">
<property name="taskNoticeRepository" ref="taskNoticeRepository"/>
</bean>
并删除 @Autowired 或在 TaskInterceptor 上添加 @Component 注释并从 xml 中删除 bean 声明
如果 ApplicationContext 也返回 null 实现 ApplicationContextAware 解决了问题
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringContext implements ApplicationContextAware {
private static ApplicationContext context;
public static <T extends Object> T getBean(Class<T> beanClass) {
return context.getBean(beanClass);
}
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
SpringContext.context = context;
}
}
用法
LogsRepository repository = SpringContext.getBean(LogsRepository.class);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.