拦截器中无法自动连接的字段

时间:2014-09-10 09:38:05

标签: java spring hibernate

我需要在数据库中存储对象时确定事件。我使用拦截器aproach。 拦截器类看起来像吼叫:

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

我该如何解决?

3 个答案:

答案 0 :(得分:2)

你创建了一个鸡蛋配置(或循环依赖):要创建sessionFactory,你需要拦截器。拦截器需要回购。回购需要sessionFactory

最简单的解决方案是注入ApplicationContext并添加@PostConstruct方法:

@Autowired
private ApplicationContext applicationContext;

private TaskNoticeRepository taskNoticeRepository;

@PostConstruct
public void init() {
    taskNoticeRepository = applicationContext.getBean(TaskNoticeRepository.class);
}

这会使这个设置步骤稍微向后移动并且经常有效,但它很脆弱。

对于类似的东西,我更喜欢使用“init bean”,当应用程序启动时(在main()或servlet上下文侦听器中)从应用程序上下文中获取“init bean”,在创建所有bean之后连接这些依赖项但在任何“正常”代码有机会运行之前。

所以会有一个懒惰的init bean依赖于拦截器和repo。拦截器将获得repo的setter。 bean将有一个公共init()方法,可以调用setter。

这可以避免各种“魔法”设置代码,这些代码可能会也可能不起作用。

答案 1 :(得分:0)

问题是循环依赖,设计不好..但你可以尝试

  <bean id="taskInterceptor" class="ru.librait.cs.infrastructure.service.interceptor.crm.TaskInterceptor">
 <property name="taskNoticeRepository" ref="taskNoticeRepository"/>
   </bean>

并删除@Autowired 或者在TaskInterceptor上添加@Component注释并从xml中删除bean声明

答案 2 :(得分:0)

如果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);