Spring自动装配和类继承

时间:2012-02-02 05:23:26

标签: spring inheritance autowired

我遇到了@Autowired工作的问题。对不起,如果我搞砸任何条款,我对Spring来说相对较新。

Spring Version是3.0.5.RELEASE,我在我的bean定义中使用了context:component-scan。

这适用于@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);
    }
}

通过此设置,所有我添加的'实现Dao',我得到了:

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 个答案:

答案 0 :(得分:7)

当使用@Transactional注释时,Spring在类实现接口时创建JDK代理。在您的情况下,(UserDao实现Dao&lt; User&gt;)的JDK代理将实现Dao&lt; User&gt;但不会扩展UserDao。因此,上下文中的bean将是Dao&lt; User&gt;。

当带有@Transaction批注的类没有实现接口时,Spring必须创建一个扩展UserDao的CGLIB代理。因此,上下文中的bean将是UserDao。

您可以告诉Spring在将它放入applicationContext.xml时始终使用CGLIB代理:

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

有一些缺点,但我不记得了。

我不使用proxy-target-class =“true”,我的设计是这样的:

我为每种类型的Dao都有一个界面。

 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;
 }

上下文中的bean是UserDaoJpa,它将在使用UserDao的地方注入。

答案 1 :(得分:2)

您是否曾尝试在Dao课程中自动装配UserDao界面(而不是UserResource),例如

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

    // ...
}

如果您有Dao接口的多个实现,则必须告诉Spring哪个是合适的,例如使用@Qualifier注释。