【问题标题】:unable to autowire sessionfactory bean in spring无法在春季自动装配 sessionfactory bean
【发布时间】:2014-06-07 21:28:16
【问题描述】:

我已经搜索了各种解决方案,但没有任何帮助。

ERROR: org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'roleDao': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.hibernate.SessionFactory com.oodles.app.dao.impl.RoleDAOImpl.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)}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <!-- Creates the Spring Container shared by all Servlets and Filters -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Processes application requests -->
    <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

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

    <!-- Loads Spring Security config file -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appServlet/spring-security.xml</param-value>
    </context-param>

    <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>
    <!-- spring security config ends here -->

</web-app>

servlet-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"   
    xsi:schemaLocation="http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
    http://www.springframework.org/schema/aop  
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-4.0.xsd">

  <!-- JDBC Data Source. It is assumed you have MySQL running on localhost port 3306 with 
       username root and blank password. Change below if it's not the case -->
  <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <!--
     <property name="driverClassName" value="org.postgresql.Driver"/>
    <property name="url" value="jdbc:postgresql://localhost:5432/testdb"/>
    <property name="username" value="postgres"/>
    <property name="password" value="postgres"/>
    <property name="validationQuery" value="SELECT 1"/> 
    -->

     <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/testdb"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
    <property name="validationQuery" value="SELECT 1"/> 

  </bean>

  <!-- Hibernate Session Factory -->
  <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDataSource"/>
    <property name="packagesToScan">
      <array>
        <value>com.oodles.app.domain</value>
      </array>
    </property>
    <property name="hibernateProperties">
      <value>hibernate.dialect=org.hibernate.dialect.MySQLDialect</value>
      <value>hibernate.show_sql=true</value>
    </property>
  </bean>

  <!-- Hibernate Transaction Manager -->
  <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
  </bean>

  <!-- Activates annotation based transaction management -->
  <tx:annotation-driven transaction-manager="transactionManager"/>

  <!-- Enable @Controller annotation support -->
  <mvc:annotation-driven />

  <!-- Map simple view name such as "test" into /WEB-INF/test.jsp -->
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/" />
    <property name="suffix" value=".jsp" />
  </bean>

  <mvc:resources mapping="/resources/**" location="/resources/" />

  <!-- Scan classpath for annotations (eg: @Service, @Repository etc) -->
  <context:component-scan base-package="com.oodles.app.aspectj , com.oodles.app.domain, 
                                com.oodles.app.dao, com.oodles.app.controller, 
                                com.oodles.app.services, com.oodles.app.dao.impl,
                                com.oodles.app.services.impl" />

   <aop:aspectj-autoproxy />

</beans>

spring-security.xml

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

    <mvc:annotation-driven />
    <context:component-scan base-package="com.oodles.app.aspectj , com.oodles.app.domain, 
                                com.oodles.app.dao, com.oodles.app.controller, 
                                com.oodles.app.services, com.oodles.app.dao.impl,
                                com.oodles.app.services.impl" />

    <http auto-config='true'>
        <intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <intercept-url pattern="/**" access="ROLE_ADMIN" />
        <form-login 
            login-page='/login' 
            default-target-url="/" 
            authentication-failure-url="/login?error" 
            username-parameter="j_username"
            password-parameter="j_password" />
      </http>

    <!-- <authentication-manager>
        <authentication-provider>
            <user-service>
                <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
                <user name="bob" password="bobspassword" authorities="ROLE_USER" />
            </user-service>
        </authentication-provider>
    </authentication-manager> -->


    <authentication-manager>  
        <authentication-provider user-service-ref="customUserDetailsService">  
            <password-encoder hash="plaintext">  
        </password-encoder></authentication-provider>  
    </authentication-manager> 

</beans:beans>

RoleDAO.java

package com.oodles.app.dao;

import com.oodles.app.domain.Role;

public interface RoleDAO
{
    public Role getRole(int id);
}

RoleDAOImpl.java

package com.oodles.app.dao.impl;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.oodles.app.dao.RoleDAO;
import com.oodles.app.domain.Role;

@Repository(value="roleDao")
public class RoleDAOImpl implements RoleDAO {

    @Autowired
    private SessionFactory sessionFactory;

    private Session getCurrentSession() {
        return sessionFactory.getCurrentSession();
    }

    public Role getRole(int id) {
        Role role = (Role) getCurrentSession().load(Role.class, id);
        return role;
    }
}

我还尝试在 RoleDAOImpl 中添加 @Qualifier("sessionFactory") 和 @Autowired。但是没用。

请帮忙。

【问题讨论】:

    标签: java spring hibernate spring-mvc spring-security


    【解决方案1】:

    问题在于您在 Servlet 容器中引导 Spring 的方式。

    在 web.xml 中,您正在从 spring-security.xml 创建一个根应用程序上下文,并且还从 servlet-context.xml 创建一个 Web 应用程序上下文。

    问题在于 Web 应用程序上下文中的 bean 对根应用程序上下文中的 bean 不可见。

    您遇到的问题有多种解决方案,其中之一是将与数据库相关的配置移动到根应用程序上下文中。你的 web.xml 看起来像这样:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    
        <!-- Creates the Spring Container shared by all Servlets and Filters -->
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
        <!-- Processes application requests -->
        <servlet>
           <servlet-name>appServlet</servlet-name>
           <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
           <init-param>
              <param-name>contextConfigLocation</param-name>
              <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
           </init-param>
           <load-on-startup>1</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>appServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
        <!-- Loads Root application context -->
        <context-param>
           <param-name>contextConfigLocation</param-name>
           <param-value>/WEB-INF/spring/appServlet/applicationContext.xml</param-value>
        </context-param>
    
        <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>
        <!-- spring security config ends here -->
    
    </web-app>
    

    我已将spring-security.xml 重命名为applicationContext.xml,它包含您的spring-security.xml 包含的代码以及额外的以下代码(从servlet-context.xml 移动):

    <!-- JDBC Data Source. It is assumed you have MySQL running on localhost port 3306 with 
           username root and blank password. Change below if it's not the case -->
      <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <!--
         <property name="driverClassName" value="org.postgresql.Driver"/>
        <property name="url" value="jdbc:postgresql://localhost:5432/testdb"/>
        <property name="username" value="postgres"/>
        <property name="password" value="postgres"/>
        <property name="validationQuery" value="SELECT 1"/> 
        -->
    
         <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/testdb"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
        <property name="validationQuery" value="SELECT 1"/> 
    
      </bean>
    
      <!-- Hibernate Session Factory -->
      <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="myDataSource"/>
        <property name="packagesToScan">
          <array>
            <value>com.oodles.app.domain</value>
          </array>
        </property>
        <property name="hibernateProperties">
          <value>hibernate.dialect=org.hibernate.dialect.MySQLDialect</value>
          <value>hibernate.show_sql=true</value>
        </property>
      </bean>
    
      <!-- Hibernate Transaction Manager -->
      <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
      </bean>
    
      <!-- Activates annotation based transaction management -->
      <tx:annotation-driven transaction-manager="transactionManager"/>
    

    【讨论】:

    • 感谢您的回答。但我收到此错误:IOException parsing XML document from ServletContext resource [/WEB-INF/applicationContext.xml];嵌套异常是 java.io.FileNotFoundException: 无法打开 ServletContext 资源 [/WEB-INF/applicationContext.xml]
    • 感谢@geo,它起作用了。但目前我对根应用程序上下文和 Web 应用程序上下文一无所知。区分它们。我想了解这个概念。(任何有用的链接)如果我们必须配置多个 xml 文件怎么办。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-02
    • 2012-08-10
    • 1970-01-01
    • 2017-12-13
    • 1970-01-01
    • 2018-12-26
    • 2015-12-11
    相关资源
    最近更新 更多