2016-05-22 4 views
0

Meine Klassen wie folgt aussehen: AbstractDAOKomponente-Scan zu finden, nicht @Repositoy

package dao.impl; 
public abstract class AbstractDAO <E> implements DAO<E> { 

@PersistenceContext 
private EntityManager em; 

    public void add(E entity) { 
     em.persist(entity); 
    } 
} 

DAOImpl

package dao.impl; 
@Transactional 
@Repository 
public class ItemDAOImpl extends AbstractDAO<Item> { 

} 

anwendungskontext test.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:context="http://www.springframework.org/schema/context" 
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" 
xsi:schemaLocation="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 
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd 
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> 

<context:component-scan base-package="dao.impl" /> 

<bean id="entityManagerFactoryBean" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 

    <property name="packagesToScan" value="domain" /> 

    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> 
    </property> 
    <property name="jpaProperties"> 
     <props> 
      <prop key="hibernate.archive.autodetection">class</prop> 
      <prop key="hibernate.hbm2ddl.auto">create</prop> 
      <prop key="hibernate.show_sql">true</prop> 
      <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
     </props> 
    </property> 
</bean> 

<bean id="dataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
    <property name="url" value="jdbc:mysql://localhost:3306/inventory" /> 
    <property name="username" value="root" /> 
    <property name="password" value="1234" /> 
</bean> 

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactoryBean" /> 
</bean> 

<tx:annotation-driven /> 

TEST-Klasse

package service.impl; 

@ContextConfiguration(locations = "classpath:application-context-test.xml") 
@RunWith(SpringJUnit4ClassRunner.class) 
public class ItemTest { 

@Autowired 
private ItemDAOImpl itemDAO; 

@Test 
public void testCreateItem() throws Exception { 
    Item item = new Item("cellphone", "galaxy", ItemType.TECHNOLOGY, 10000); 
    itemDAO.add(item);   
    assertEquals(5, itemDAO.list(Item.class).size()); 
} 
} 

Sollte dieser Code nicht in der Lage sein, mein itemDAO automatisch zu aktivieren?

Wenn ich meinen Test laufen wirft es eine Ausnahme zu sagen

org.springframework.beans.factory.BeanCreationException: Could not autowire 
field: private dao.impl.ItemDAOImpl service.impl.ItemTest.itemDAO; nested 
exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type [dao.impl.ItemDAOImpl] found for dependency: 
expected at least 1 bean which qualifies as autowire candidate for this 
dependency. Dependency annotations: 

Könnten Sie bitte sagen, was bin ich dabei? Das Einzige, woran ich denken kann, ist, dass mein Application-Context-Test.xml in src/test/resources und mein Dao in src/main/java ist, da mein Test in src/test/java ist. Vielleicht das Scannen von Komponenten-Scan an der falschen Stelle?

Antwort

2

Da ItemDAOImpl mit @Transactional gekennzeichnet ist, erstellt spring einen Proxy für diese Bean und injiziert den Proxy, nicht die Bean selbst beim Autowiring.

Spring kann Proxys durch Unterklassen (mit Cglib) oder durch Implementierung der Beans-Schnittstellen mit Jdk-Proxies erstellen. Welcher Typ von Proxy-Spring verwendet wird, hängt von Ihrer Konfiguration ab.

Ich hatte ähnliche Probleme wie Sie beschrieben und die Ursache war, dass der Frühling Jdk Proxies verwendet und ich war mir dessen nicht bewusst.

In Ihrem Fall wäre die Spring Bean für ItemDaoImpl ein Proxy, der DAO implementiert. Dies kann nicht in

@Autowired 
private ItemDAOImpl itemDAO; 

injiziert werden, da es nicht zu ItemDaoImpl gegossen werden kann. Das würde die Ausnahme erklären, der Sie gegenüberstehen.

Um das zu beheben, das Feld

@Autowired 
private DAO<Item> itemDAO; 

Das funktioniert nur oben

ändern, wenn Sie Feder Sie 4.

Bei früheren Versionen der Feder verwenden eine Schnittstelle

public interface ItemDAO extends DAO<Item> 
erstellen

und lassen Sie ItemDaoImpl es implementieren. Schließlich ändern Sie Ihr Feld, wo Sie möchten, dass es injiziert werden

@Autowired 
private ItemDAO itemDAO; 
+0

Es funktionierte perfekt, ich versuchte beide Ansätze und beide waren erfolgreich. Danke Stefan, auch für die Erklärung. –