【问题标题】:Spring Autowiring and Class InheritanceSpring自动装配和类继承
【发布时间】:2012-02-24 19:47:57
【问题描述】:

我在让@Autowired 工作时遇到问题。对不起,如果我搞砸了任何条款,我对 Spring 比较陌生。

Spring 版本是 3.0.5.RELEASE,我在我的 beans 定义中使用 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);
    }
}

通过这个设置,我添加了“implements 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>

谁能解释一下这个问题?我很想保留类继承。

谢谢!

【问题讨论】:

  • 您是否在上下文文件中定义了 bean?如果您有多个 UserDao bean,请尝试使用 @qualifier@autowire
  • 类路径中只有一个UserDao,我的beans文件中使用的是
  • 当您收到NoSuchBeanDefinitionException 时,您似乎没有在上下文文件中定义 bean。请您发布您的上下文文件
  • 已发布。我已经在没有&lt;bean id="userDao" class="web.rs.persistence.dao.UserDao"/&gt; 的情况下尝试了它,但没有运气。请记住,仅添加接口就会使其中断。
  • 尝试使用@Repository 而不是@Component 同时检查根异常还是这是您日志中唯一的异常?

标签: spring inheritance autowired


【解决方案1】:

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

当带有@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 的地方。

【讨论】:

  • 当我尝试您的建议时,我收到以下异常:Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [web.rs.persistence.dao.UserDao]: Specified class is an interface ... 有什么建议吗? (注意:我没有走proxy-target-classes的路线)
  • 如果你使用的是组件扫描,是不是UserDaoJpa类上的@Component注解?否则,您必须以这种方式创建 bean:。你不能有这个: 因为它会尝试实例化一个接口
【解决方案2】:

您是否尝试在UserResource 类中自动连接Dao 接口(而不是UserDao),例如

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

    // ...
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-27
    • 2015-09-17
    • 1970-01-01
    相关资源
    最近更新 更多