NoSuchBeanDefinitionException 如何初始化 SessionFactory bean?

Posted

技术标签:

【中文标题】NoSuchBeanDefinitionException 如何初始化 SessionFactory bean?【英文标题】:NoSuchBeanDefinitionException How to initialise SessionFactory bean? 【发布时间】:2013-09-25 12:32:03 【问题描述】:

我有一个问题。我尝试使用 Spring 和 Hibernate 运行我的 Web 应用程序/我有一个奇怪的错误。 NoSuchBeanDefinitionException。堆栈跟踪是:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.hibernate.SessionFactory] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: @org.springframework.beans.factory.annotation.Autowired(required=true)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:967)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:837)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:749)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486)

我不知道为什么,因为在我的 servlet-context.xml 中我声明了 SessionFacory bean:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
    http://www.springframework.org/schema/beans     
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.2.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

<context:component-scan base-package="com.example" />
<context:component-scan base-package="com.example.service" />
<context:component-scan base-package="com.example.service.impl" />
<context:component-scan base-package="com.example.dao" />
<context:component-scan base-package="com.example.dao.impl.hibernate" />
<context:component-scan base-package="com.example.web.controller" />
<context:component-scan base-package="com.example.entity" />

<mvc:annotation-driven />

<tx:annotation-driven />

<bean
    class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />

<bean
    class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />

<bean id="viewResolver"
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass"
        value="org.springframework.web.servlet.view.JstlView" />
    <property name="prefix" value="/WEB-INF/pages/" />
    <property name="suffix" value=".jsp" />
</bean>

<bean id="userService" class="com.example.service.impl.UserServiceImpl">
    <property name="userDAO" ref="userDAO" />
</bean>

<bean id="userDAO" class="com.example.dao.impl.hibernate.HibernateUserDAO" />

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="org.h2.Driver" />
    <property name="url" value="jdbc:h2:~/userdb" />
    <property name="username" value="user" />
    <property name="password" value="pswd" />
</bean>

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="annotatedClasses">
        <list>
            <value>com.example.entity.User</value>
            <value>com.example.entity.Role</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <value>
            hibernate.dialect=org.hibernate.dialect.H2Dialect
            hibernate.show_sql=true
        </value>
    </property>
</bean>

<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

另外,我注释了所有 DAO 实现和服务实现。 有什么想法吗?

已添加

这是我的代码的一部分:

@Repository
public class HibernateUserDAO implements UserDAO 
   @Autowired
   private SessionFactory sessionFactory;
   ...

和服务类:

@Service
public class UserServiceImpl implements UserService, UserDetailsService 
@Autowired
private UserDAO userDAO;

@Override
@Transactional
public void create(User user) throws SQLException 
    userDAO.create(user);

完整的堆栈跟踪:

Sep 20, 2013 10:54:10 AM org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class   
org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name         'hibernateUserDAO': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.hibernate.SessionFactory com.example.dao.impl.hibernate.HibernateUserDAO.sessionFactory; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.hibernate.SessionFactory] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: @org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=sessionFactory)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1120)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4939)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
 Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire               field: private org.hibernate.SessionFactory    com.example.dao.impl.hibernate.HibernateUserDAO.sessionFactory; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.hibernate.SessionFactory] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: @org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=sessionFactory)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:514)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
... 23 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.hibernate.SessionFactory] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: @org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=sessionFactory)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:967)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:837)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:749)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486)
... 25 more

这是我的 web.xml

<?xml version="1.0" encoding="UTF-8"?>

http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/root-context.xml
        /WEB-INF/application-security.xml
    </param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
    <filter-name>hibernateFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>hibernateFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

【问题讨论】:

不要让 Hibernate 在你的类路径上。确保 Hibernate 及其所有依赖项都在您的 lib 文件夹中。 我确定我的类路径和 lib 文件夹中的所有必需的 jars 简而言之,您的 bean 位于错误的位置,旁边有很多重复项。如需更长的版本,请参阅我的答案。 【参考方案1】:

我会先清理你的配置

这个

<context:component-scan base-package="com.example" />

包括所有这些

<context:component-scan base-package="com.example" />
<context:component-scan base-package="com.example.service" />
<context:component-scan base-package="com.example.service.impl" />
<context:component-scan base-package="com.example.dao" />
<context:component-scan base-package="com.example.dao.impl.hibernate" />
<context:component-scan base-package="com.example.web.controller" />
<context:component-scan base-package="com.example.entity" />

您正在使用组件扫描,因此无需显式定义所有 bean(如果仍然需要,它会使组件扫描变得毫无用处)。

接下来这两个豆子

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />

已经被&lt;mvc:annotation-driven /&gt;暗示了

基本上只剩下这个

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
    http://www.springframework.org/schema/beans     
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.2.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

<context:component-scan base-package="com.example" />

<mvc:annotation-driven />
<tx:annotation-driven />

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass"
        value="org.springframework.web.servlet.view.JstlView" />
    <property name="prefix" value="/WEB-INF/pages/" />
    <property name="suffix" value=".jsp" />
</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="org.h2.Driver" />
    <property name="url" value="jdbc:h2:~/userdb" />
    <property name="username" value="user" />
    <property name="password" value="pswd" />
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="annotatedClasses">
        <list>
            <value>com.example.entity.User</value>
            <value>com.example.entity.Role</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <value>
            hibernate.dialect=org.hibernate.dialect.H2Dialect
            hibernate.show_sql=true
        </value>
  </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

不会解决你的问题,因为报错不是因为配置不完整,而是配置放错了地方。 datasourcesessionFactorytransactionManager&lt;tx:annotation-driven .. /&gt; 必须移动到 applicationContext.xml。除此之外,您的 applicationContext.xml 还应该包含一个组件扫描,它会扫描所有控制器。

    <context:component-scan base-package="com.example">
    <context:exclude-filter type="annotation" value="org.springframework.stereotype.Controller" />
</context:component-scan">

将 servlet-context.xml 中的 &lt;component-scan .. /&gt; 更改为

<context:component-scan base-package="com.example" use-default-filters="false">
    <context:include-filter type="annotation" value="org.springframework.stereotype.Controller" />
</context:component-scan">

这是为了防止 @Service@Repository bean 的重复实例化。这就是现在发生的事情(您的ContextLoaderListenerDispatcherServlet 都在加载和创建相同的bean,这将导致您出现其他不错的异常,并且在内存重复旁边,因为您在内存中有每个bean 的2 个实例) .

【讨论】:

为什么我需要 2 个 xml 文件?我看到了很多带有 1 个 xml 的示例。所以,我不明白这两个文件分别应该是什么? 从 yuo stacktrace 判断,您有一个 ContextLoaderListener(并且您正在使用 Spring Security)和一个 DispatcherServlet。他们应该都加载相同的xml文件。发布您的 web.xml。 您已经有多个文件,所以我看不到问题所在。基本上我提到 applicationContext.xml 你应该阅读 root-context.xml 和 servlet-context.xml == dispatcher-servlet.xml。【参考方案2】:

Spring 有时真正想说的是:

There are multiple bean definitions...

我遇到了这个问题:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'metadataGeneratorFilter' is defined

曾经我有一个这样的 xml 文件:

<security:custom-filter ref="metadataGeneratorFilter" before="CHANNEL_FILTER"/>

<beans:bean id="metadataGeneratorFilter"
            class="org.springframework.security.saml.metadata.  MetadataGeneratorFilter">
    <beans:constructor-arg ref="metadataGenerator"/>
</beans:bean>

【讨论】:

【参考方案3】:

如果您使用@Autowired,则无需在上下文中声明为属性。但它必须在上下文--->NoSuchBeanDefinition--> 找不到它。

<bean id="userService" class="com.example.service.impl.UserServiceImpl">
    <property name="userDAO" ref="userDAO" /> 
</bean>

尝试从属性上下文中删除 userDAO。--如果您自动装配它,则在上下文中不需要它。

但问题似乎出在这个 bean 上:

<bean id="userDAO" class="com.example.dao.impl.hibernate.HibernateUserDAO" />

无法注入 sessionFactory 的依赖,但一切似乎都是正确的 :( 为什么不尝试删除会话工厂的@autowired,在 hibernateUserDao 的上下文中放置 get/set 一个 add 属性 ref,只是为了测试会发生什么?

【讨论】:

以上是关于NoSuchBeanDefinitionException 如何初始化 SessionFactory bean?的主要内容,如果未能解决你的问题,请参考以下文章