2013-10-10 3 views
0

Я получаю сообщение об ошибке при попытке автоподготовки класса, расширяющего JdbcDaoSupport. У меня есть классы DAO и классы Controller, разделенные на два разных контекста весны. Классы DAO находятся в корневом контексте, а классы Controller находятся в контексте сервлета. Я установил компонентное сканирование, чтобы не было перекрытия между bean-компонентами между двумя контекстами (это правильный шаблон?). Все эти факторы в сочетании с тем, что мои DAO расширяют JdbcDaoSupport, похоже, вызывают проблему, и я не понимаю, почему. Я просто изучаю весну, поэтому пока не понимаю все концепции.Spring Autowire JdbcDaoSupport

EDIT: Такое поведение, по-видимому, вызвано тем, что JdbcDaoSupport/DaoSupport реализует интерфейс InitializingBean. Тем не менее, все еще запутано.

Здесь ошибка я получаю:

Error creating bean with name 'homeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.test.dao.CustomerDAO2 org.test.servlet.HomeController.customerDAO; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.test.dao.CustomerDAO2] 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)} 

Вот мои файлы:

HomeController.java

package org.test.servlet; 

import java.util.Locale; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Controller; 
import org.springframework.ui.Model; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 

import org.test.dao.*; 

@Controller 
public class HomeController 
{ 
    @Autowired 
    CustomerDAO2 customerDAO; 

    @RequestMapping(value = "/", method = RequestMethod.GET) 
    public String home(Locale locale, Model model) 
    { 
     model.addAttribute("customer", customerDAO.getCustomer()); 
     return "home"; 
    } 
} 

CustomerDAO2.java

package org.test.dao; 

import java.sql.ResultSet; 
import java.sql.SQLException; 
import javax.sql.DataSource; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.jdbc.core.*; 
import org.springframework.jdbc.core.support.JdbcDaoSupport; 
import org.springframework.stereotype.Repository; 
import org.springframework.transaction.annotation.*; 
import org.test.dto.Customer; 

@Repository 
public class CustomerDAO2 extends JdbcDaoSupport 
{ 
    public CustomerDAO2() 
    { 
    } 

    @Autowired 
    public CustomerDAO2(DataSource datasource) 
    { 
     this.setDataSource(datasource); 
    } 

    @Transactional 
    public Customer getCustomer() 
    { 
     JdbcTemplate jdbcTemplate = new JdbcTemplate(getDataSource()); 
     Customer customer = jdbcTemplate.queryForObject("select * from customer", new CustomerMapper()); 
     return customer; 
    } 

    public static class CustomerMapper implements RowMapper<Customer> 
    { 
     public Customer mapRow(ResultSet rs, int rowNum) throws SQLException 
     { 
      Customer customer = new Customer(); 
      customer.setCustomerId(rs.getInt("customerId")); 
      customer.setCustomerNumber(rs.getString("customerNumber")); 
      return customer; 
     } 
    } 
} 

приложений 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:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation=" 
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 

    <!-- Scans within the base package of the application for @Components to configure as beans --> 
    <!-- @Controller, @Service, @Configuration, etc. --> 
    <context:component-scan base-package="org.test"> 
    <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/> 
    </context:component-scan> 

    <!-- Enables the configuration of transactional behavior based on annotations --> 
    <tx:annotation-driven transaction-manager="transactionManager"/> 

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
    <property name="url" value="jdbc:mysql://localhost/crm?user=root&amp;password=password" /> 
    </bean> 

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="dataSource"/> 
    </bean> 

</beans> 

сервлет-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:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation=" 
     http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd 
     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 

    <!-- Scans within the base package of the application for @Components to configure as beans --> 
    <!-- @Controller, @Service, @Configuration, etc. --> 
    <context:component-scan base-package="org.test.servlet"/> 

    <!-- Enables the Spring MVC @Controller programming model --> 
    <mvc:annotation-driven /> 

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory --> 
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
     <property name="prefix" value="/WEB-INF/views/" /> 
     <property name="suffix" value=".jsp" /> 
    </bean> 

</beans> 

ответ

1

Я нашел ответ на этот пост:

Spring expected at least 1 bean which qualifies as autowire candidate for this dependency


В принципе, мне нужно создать интерфейс для моих классов DAO. Что-то вроде этого:

public interface ICustomerDAO { 
    Customer getCustomer(); 
} 

Примечание: вероятно, было бы лучше, чтобы сделать более общий интерфейс CRUD.

Затем вы используете тип интерфейса для инъекции зависимостей вместо того, чтобы использовать тип класса:

@Autowired 
ICustomerDAO customerDAO; 

Причина этого необходимо потому, что Spring создает основные классы прокси:

http://insufficientinformation.blogspot.com/2007/12/spring-dynamic-proxies-vs-cglib-proxies.html

http://docs.spring.io/spring/docs/2.5.x/reference/aop.html#aop-proxying

Смежные вопросы