Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Spring,如何将子bean注入父bean?_Java_Spring - Fatal编程技术网

Java 使用Spring,如何将子bean注入父bean?

Java 使用Spring,如何将子bean注入父bean?,java,spring,Java,Spring,我有一个Bean想要注入它的子类,如下所示: 家长: package test; @Component public class Parent { @Autowired Child child; public Child getChild() { return child; } } 儿童: package test; @Component public class Child extends Parent { } 这将导致以下错误: org.springfram

我有一个Bean想要注入它的子类,如下所示:

家长:

package test;

@Component
public class Parent {
  @Autowired
  Child child;

  public Child getChild() {
    return child;
  }
}
儿童:

package test;

@Component
public class Child extends Parent {
}
这将导致以下错误:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [test.Child] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency
删除
extensedparent
位会使一切按预期工作,因此Spring似乎无法找到子级,就好像父级以某种方式对其进行了跟踪。如何配置Spring以正确连接这些子实例?我正在使用Java类配置,如下所示:

@Configuration
@ComponentScan(basePackages = "test")
public class AppConfig {
}
我尝试过使用
@Qualifier
注释,并在
AppConfig
中指定不同的名称,如下所示,但没有任何帮助:

@Bean(name = "parent")
public Parent parent() {
  return new Parent();
}

@Bean(name = "child")
public Child child() {
  return new Child();
}

为了让Spring将子类视为自己独特的实体,我不确定缺少什么成分。这是不可能的吗?

因为
扩展了
,必须构造
来构造
,但是
需要
来构造。这是一个循环依赖;避免在代码中创建循环依赖项

您需要重构代码。这在您的代码库中可能不可能实现,但如果您可以反转关系,以便
父级
扩展
子级
(而不是现在的反向),您将能够注入:

package hello;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    @Autowired
    private Parent parent;
    @Bean
    Child makeChild() { return new Child(); }
}
@Component
class Parent extends Child {
    @Autowired
    private Child child;

    public Child getChild() { return this.child; }
}
class Child {
}
或者,将
子级
父级
都需要的代码重构到另一个类中,并将该代码注入
父级
子级

package hello;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    @Autowired
    private Parent parent;
    @Bean
    Child makeChild() { return new Child(); }
    @Bean
    Shared makeShared() { return new Shared(); }
}
@Component
class Parent {
    @Autowired
    private Shared shared;
    @Autowired
    private Child child;
    public Child getChild() { return this.child; }
}
class Child {
    @Autowired
    private Shared shared;
}
class Shared {
}

由于
子项
扩展了
父项
,因此必须构造
父项
来构造
子项
,但是
父项
需要一个子项
来构造。这是一个循环依赖;避免在代码中创建循环依赖项

您需要重构代码。这在您的代码库中可能不可能实现,但如果您可以反转关系,以便
父级
扩展
子级
(而不是现在的反向),您将能够注入:

package hello;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    @Autowired
    private Parent parent;
    @Bean
    Child makeChild() { return new Child(); }
}
@Component
class Parent extends Child {
    @Autowired
    private Child child;

    public Child getChild() { return this.child; }
}
class Child {
}
或者,将
子级
父级
都需要的代码重构到另一个类中,并将该代码注入
父级
子级

package hello;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    @Autowired
    private Parent parent;
    @Bean
    Child makeChild() { return new Child(); }
    @Bean
    Shared makeShared() { return new Shared(); }
}
@Component
class Parent {
    @Autowired
    private Shared shared;
    @Autowired
    private Child child;
    public Child getChild() { return this.child; }
}
class Child {
    @Autowired
    private Shared shared;
}
class Shared {
}

我通过修改Parent的定义解决了这个问题,如下所示:

package test;

@Primary
@Component
public class Parent {
  @Resource
  Child child;

  public Child getChild() {
    return child;
  }
}
package test;

@Component("child")
public class Child extends Parent {
}
并对子对象进行如下修改:

package test;

@Primary
@Component
public class Parent {
  @Resource
  Child child;

  public Child getChild() {
    return child;
  }
}
package test;

@Component("child")
public class Child extends Parent {
}
我已将
@Autowired
注释替换为
@Resource
,该注释尝试在键入之前按名称进行查找,并向子类添加了显式名称。为了在尝试自动关联父对象时消除父对象与子对象之间的歧义,我还向父对象添加了
@Primary
注释


我仍然不完全理解按类型查找失败的原因,这迫使我使用
@Resource
按名称查找bean。

我通过修改父定义解决了这个问题,如下所示:

package test;

@Primary
@Component
public class Parent {
  @Resource
  Child child;

  public Child getChild() {
    return child;
  }
}
package test;

@Component("child")
public class Child extends Parent {
}
并对子对象进行如下修改:

package test;

@Primary
@Component
public class Parent {
  @Resource
  Child child;

  public Child getChild() {
    return child;
  }
}
package test;

@Component("child")
public class Child extends Parent {
}
我已将
@Autowired
注释替换为
@Resource
,该注释尝试在键入之前按名称进行查找,并向子类添加了显式名称。为了在尝试自动关联父对象时消除父对象与子对象之间的歧义,我还向父对象添加了
@Primary
注释


我仍然不完全理解为什么按类型查找失败,迫使我使用
@Resource
按名称查找bean。

请原谅,但我不理解您的代码片段中真正解决问题的部分。我看到您删除了Child上的
@组件
注释,但对我的组件做同样的操作不会改变任何东西。您还创建了一个新类,并在我的问题中省略了一个类,我不清楚这会如何改变解决方案。我错过了
上的
扩展父
-这会创建循环依赖关系,这就是您看到此问题的原因。我会更新我的答案。看起来我也忽略了这个遗漏。我不认为循环依赖是这个问题的原因。我可以轻松创建两个相互自动连接的类,而不会出现问题,我发现通过将
@Autowired
注释更改为
@Resource
,可以避免此错误。这意味着问题与类型查找本身有关,不是吗?请原谅,但我不理解代码片段中真正解决问题的部分。我看到您删除了Child上的
@组件
注释,但对我的组件做同样的操作不会改变任何东西。您还创建了一个新类,并在我的问题中省略了一个类,我不清楚这会如何改变解决方案。我错过了
上的
扩展父
-这会创建循环依赖关系,这就是您看到此问题的原因。我会更新我的答案。看起来我也忽略了这个遗漏。我不认为循环依赖是这个问题的原因。我可以轻松创建两个相互自动连接的类,而不会出现问题,我发现通过将
@Autowired
注释更改为
@Resource
,可以避免此错误。这意味着问题与类型查找本身有关,不是吗?这对我来说失败了,@user108471,初始错误;我正在使用Spring Boot 1.3.3&JDK 8,它在Linux上使用Spring 4.2.5。@JanNielsen抱歉,看起来我遗漏了另一个重要的更改:向子类添加显式名称。这对我来说失败,@user108471,初始错误;我使用的是Spring Boot 1.3.3&JDK 8,它在Linux上使用Spring 4.2.5。@JanNielsen抱歉,看起来我遗漏了另一个重要的更改:为子类添加显式名称。