2012-02-02 4 views
1

У меня возникла проблема с получением @Autowired для работы. Извините, если я испортил любые условия, я относительно новичок в Spring.Spring Autowiring и Class Inheritance

Весенняя версия 3.0.5.RELEASE, и я использую контекст: компонентное сканирование в определении моих компонентов.

Это работает с @Autowired аннотации:

@Component 
public class UserDao { 
    @PersistenceContext 
    protected EntityManager em; 

    @Transactional 
    public User findById(Long id) { 
     return em.find(User.class, id); 
    } 
} 

Это не работает с @Autowired аннотации:

@Component 
public class UserDao implements Dao<User> { 
    @PersistenceContext 
    protected EntityManager em; 

    @Transactional 
    public User findById(Long id) { 
     return em.find(User.class, id); 
    } 
} 

С помощью этой установки, все я добавил 'реализует Дао', и я получаю:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [web.rs.persistence.dao.UserDao] 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)} 

И вот некоторые другие классы для справки:

Dao.java (интерфейс):

public interface Dao<T extends BaseEntity> { 
    T findById(Long id); 
} 

UserResource.java:

@Component 
public class UserResource { 
    @Autowired 
    UserDao userDao; 

    public User getUser(Long id) { 
     return userDao.findById(id); 
    } 
} 

applicationContext.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" 
     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.0.xsd"> 

     <context:component-scan base-package="web.rs" /> 

     <bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
      <property name="location" value="classpath:config.properties" /> 
     </bean> 

     <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
      <property name="loadTimeWeaver"> 
       <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" /> 
      </property> 
      <property name="persistenceUnitName" value="${persistence.unit}" /> 
     </bean> 

     <bean id="trx-manager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
      <property name="entityManagerFactory" ref="emf" /> 
     </bean> 

     <tx:annotation-driven transaction-manager="trx-manager" /> 
    </beans> 

Может кто-нибудь пролить некоторый свет по этому вопросу? Я бы хотел сохранить классовое наследование.

Спасибо!

+0

Вы определили компонент в своем файле контекста? Если у вас есть несколько компонентов UserDao, попробуйте использовать '@ qualifier' вместе с' @ autowire' –

+0

. В пути к классам есть только один UserDao, и я использую в файле beans. –

+0

как вы получаете 'NoSuchBeanDefinitionException', кажется, вы havnt определили bean-компонент в файле context.Can, пожалуйста, разместите свой файл контекста –

ответ

7

При использовании аннотации @Transactional Spring создает прокси-сервер JDK, когда класс реализует интерфейс. В вашем случае прокси-сервер JDK (UserDao реализует Dao <User>) реализует Dao < Пользователь >, но не будет расширять UserDao. Таким образом, bean в контексте будет Dao < Пользователь >.

Когда класс с аннотацией @Transaction не реализует интерфейс, Spring должен создать прокси CGLIB, который расширяет UserDao. Таким образом, компонент в контексте будет UserDao.

Вы можете сказать, Spring всегда использовать CGLIB прокси при вводе этого в вашем applicationContext.xml:

<tx:annotation-driven transaction-manager="trx-manager" proxy-target-class="true" /> 

Есть некоторые недостатки, но я их не помню.

Я не использую прокси-целевого класса = «истинный» и мой дизайн, как это:

У меня есть интерфейс для каждого типа Дао.

public interface UserDao extends Dao<User> 

    List<User> findByUsername(); 

Я реализовать конкретный интерфейс

@Component 
public class UserDaoJpa implements UserDao 

    public List<User> findByUsername() { 
    ... 
    } 

Мои классы обслуживания использует UserDao:

public class UserService { 

    @Autowired 
    private UserDao userDao; 
} 

Фасоль в контексте является UserDaoJpa, и он будет впрыскивать где UserDao является используемый.

+0

Когда я попробую ваше предложение, я получаю следующее исключение: 'Caused by: org.springframework.beans.BeanInstantiationException: не удалось создать экземпляр класса bean [web.rs.persistence.dao.UserDao]: указанный класс является интерфейсом'. .. какие-либо предложения? (ПРИМЕЧАНИЕ. Я не пошел по пути «proxy-target-classes») –

+0

Если вы используете компонентное сканирование, это аннотация @Component в классе UserDaoJpa? В противном случае вам нужно создать компонент таким образом: . У вас не должно быть этого: , потому что он попытается создать экземпляр интерфейса –

2

Вы пытались автоподключить интерфейс Dao (а не UserDao) в своем классе UserResource, например.

@Component 
public class UserResource { 
    @Autowired 
    Dao<User> userDao; 

    // ... 
} 

Если у вас есть несколько реализаций интерфейса Dao, вы должны сказать Spring, который является подходящим один, например, с помощью @Qualifier аннотацию.

+0

Удивительно! Вот так! Спасибо Спасибо! –