I have a big issue with the dependency jnjection of Spring. I created a class ObjectJPA
, that implements my DAO interface. Now I want to test it within a JUnit testcase. But I get a NoSuchBeanDefinitionException
.
This is the beginning of the test:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:Spring-Common.xml" })
public class Test {
@Autowired
ObjectJPA jpa;
}
And this is the bean
package model.dao.jpa;
@Repository
public class ObjectJPA implements ObjectDAO { … }
content of the Spring-Common.xml
<bean class="….ObjectJPA" />
the declaration of the interface
package model.dao;
public interface ObjectDAO {
Content of the Spring-Common.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<context:component-scan base-package="model.dao.jpa" />
<bean class="model.dao.jpa.ObjectJPA" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="model" />
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
</bean>
<context:annotation-config />
<tx:annotation-driven />
</beans>
Do you have any ideas? Which information do you need to get a better impact?
The actual type of the bean, for Spring, is the type of its interface, and not its concrete type. So you should have
@Autowired
private ObjectDAO jpa;
and not
@Autowired
private ObjectJPA jpa;
Indeed, Spring by default uses Java interface proxies to implement AOP. And it thus needs to inject its own proxy, which implements all the interfaces of your bean and wraps it, but is not an instance of its concrete class. And that's not a problem, because the whole point of using interfaces is to use them when referencing objects, rather than using the concrete type of the object (just like you use the type List
to refer to a List, and not the type ArrayList
).