Пружинная электропроводка и наследование классов - PullRequest
1 голос
/ 02 февраля 2012

У меня проблема с получением @Autowired на работу. Извините, если я облажался, я относительно новичок в Spring.

Spring Version - 3.0.5.RELEASE, и я использую context: component-scan в своем определении bean-компонентов.

Работает с аннотацией @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>

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

Спасибо!

Ответы [ 2 ]

7 голосов
/ 03 февраля 2012

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

Если класс с аннотацией @Transaction не реализует интерфейс, Spring должен создать прокси-сервер CGLIB, расширяющий UserDao. Следовательно, bean-компонент в контексте будет UserDao.

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

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

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

Я не использую 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.

2 голосов
/ 02 февраля 2012

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

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

    // ...
}

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

...