繁体   English   中英

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

[英]With Spring, how can I inject a child bean in a parent bean?

我有一个想要注入其子类的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

删除extends Parent位会使一切按预期方式工作,因此似乎Spring无法找到Child,好像Parent以某种方式对其进行了遮盖一样。 如何配置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将Child类视为其自己的独立实体,缺少哪些成分。 这不可能吗?

我已经通过修改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扩展了Parent ,因此必须构造一个Parent来构造一个Child但是Parent需要一个Child来构造。 这是一个循环依赖关系; 避免在代码中创建循环依赖关系。

您将需要重构代码。 在您的代码库中,这可能是不可能的,但是如果您可以反转关系以使Parent扩展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(); }
}
@Component
class Parent extends Child {
    @Autowired
    private Child child;

    public Child getChild() { return this.child; }
}
class Child {
}

或者,将ChildParent需要的代码重构到另一个类中,并将该代码注入ParentChild

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM