【问题标题】:Spring Autowiring only works with InterfaceSpring 自动装配仅适用于接口
【发布时间】:2011-09-24 13:45:15
【问题描述】:

我对 Spring 框架很陌生,遇到了以下问题。

我有一个接口ClassA,由ClassA1ClassA2类实现。

我已将以下 bean 定义添加到 applicationContext.xml

<bean id="class1" class="com.abc.ClassA1" />
<bean id="class2" class="com.abc.ClassA2" />

我想自动装配两个实现类,如下所示。

@Autowired
private ClassA1 classA1;

@Autowired
private ClassA2 classA2;

上面的代码抛出错误

无法自动写入字段:com.abc.ClassA1 com.abc.SomeClass.classA1;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException: 没有匹配的 bean 类型 [com.abc.ClassA1]

但是,如果我将自动装配更改为如下界面:

@Autowired
ClassA classA1;

然后 ClassA1 自动连接到变量。我不知道如何将变量自动连接到 ClassA2。

【问题讨论】:

标签: java spring autowired


【解决方案1】:

由于某种原因,您的类由 Spring 代理。发生这种情况的原因有很多。例如,如果您使用 JPA 或 AOP,则原始类被代理。

如果一个类实现了一个接口,代理就是动态代理。所以基本上在运行时创建了一个新类,它实现了接口但不从原始类继承。因此,自动装配到原始类不起作用。

【讨论】:

  • 这意味着我必须避免在自动装配的类中使用接口?
  • 不,不。您可以自动装配接口。
  • 在我的例子中,我使用注释自动装配,一个服务是由它的接口而不是它的类自动装配的,我不得不删除接口或创建一个虚拟接口。
  • 顺便说一句,最好的做法是根本不使用自动装配。它会减慢 bean 的创建速度,从而降低应用程序的启动速度。最好使用 @Resource 并按 bean 的名称连接(而不是按类型!)
  • 嗯,有不同的架构师和不同的意见。有人说大多数bean都是单例的,因此它只影响应用程序的启动,因此不重要。但是作为开发人员,如果您的应用程序在 2 分钟而不是 30 秒内启动,可能会很烦人。我说的是相当大的应用程序。
【解决方案2】:

如果您的对象由 JDK 代理代理,那么它们应该由它们的接口引用。您可以在 aop 配置中使用 CGLIB(在类路径上)和 proxy-target-class="true"(在 applicationContext.xml 中)通过具体类制作代理

【讨论】:

  • 这是唯一可行的方法!!非常感谢。
【解决方案3】:

我尝试了多种方法来解决此问题,但我通过以下方式解决了问题。

@Autowired
private ClassA classA1;

@Autowired
private ClassA classA2;

在应用程序上下文中,我将 bean 定义如下:

<bean id="classA1" class="com.abc.ClassA1" autowire="byName" />
<bean id="classA2" class="com.abc.ClassA2" autowire="byName" />

【讨论】:

    【解决方案4】:

    你可以使用@Qualifier注解:

    @Autowired
    @Qualifier("class1")
    ClassA classA1;
    
    @Autowired
    @Qualifier("class2")
    ClassA classA2;
    

    参考:http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-autowired-annotation-qualifiers

    或者@Resource注解:

    @Resource(name="class1")
    ClassA classA1;
    
    @Resource(name="class2")
    ClassA classA2;
    

    参考:http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-resource-annotation

    【讨论】:

      【解决方案5】:

      我对自动装配抽象服务有类似的问题。您可以毫无问题地使用这样的代码:

      @Autowired
      @Qualifier("classA1")
      private ClassA1 classA1;
      
      @Autowired
      @Qualifier("classA2")
      private ClassA2 classA2;
      

      只有当你像这样声明你的 bean 时这才有效

      <bean id="class1" class="com.abc.ClassA1" />
      

      或者像这样

      @Component("classA1")
      public class ClassA1 {
      ...
      }
      

      【讨论】:

        【解决方案6】:

        从我所见的到现在,对于可以标记为@Autowired 的类的类型似乎没有任何限制。

        与问题无关,但 this 文章提及情况本身

        【讨论】:

          猜你喜欢
          • 2011-01-24
          • 2014-04-30
          • 1970-01-01
          • 2011-03-10
          • 1970-01-01
          • 1970-01-01
          • 2018-02-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多