【问题标题】:why this bean is not null为什么这个 bean 不为空
【发布时间】:2016-11-17 13:12:03
【问题描述】:

以下代码在 spring 4 中运行良好,但我想知道为什么 getBean(FooService.class) 返回一个已经加载的 bean。我认为无法保证 bean 加载的顺序,这意味着可以获得空 bean。是因为加载目标是一个类而不是字符串(即对象)还是因为 FooService bean 有一个特殊的范围,比如原型?如果是这样,getBean(class)和getBean(object)有什么区别

public abstract class AbstractService implements ApplicationContextAware {
    protected ApplicationContext applicationContext;

    protected FooService fooService;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @PostConstruct
    protected void postConstruct() {
        fooService = applicationContext.getBean(FooServiceImpl.class);
    }

【问题讨论】:

  • 我认为这是春天的感觉,没有得到空对象
  • 其实我认为你的beannull,我的意思是,你使用applicationContext来加载具体的bean对象.有了春天,你就不需要它了。您可以在 bean 参数上使用 @Autowired 注释,或者在 bean 是参数的类构造函数中或在 set 方法中使用更好。

标签: java spring


【解决方案1】:

ApplicationContext::getBean 方法创建指定类型的 bean,如果它尚未创建。

对于以下两个 bean 类:

@Component
public class Bean1 {

    @Autowired
    private ApplicationContext applicationContext;

    public Bean1() {
        System.out.println("Bean 1 constructor");
    }

    @PostConstruct
    public void init() {
        System.out.println("Bean 1 @PostConstruct started");
        applicationContext.getBean(Bean2.class);
        System.out.println("Bean 1 @PostConstruct completed");
    }
}

@Component
public class Bean2 {

    @Autowired
    private ApplicationContext applicationContext;

    public Bean2() {
        System.out.println("Bean 2 constructor");
    }

    @PostConstruct
    public void init() {
        System.out.println("Bean 2 @PostConstruct started");
        applicationContext.getBean(Bean1.class);
        System.out.println("Bean 2 @PostConstruct completed");
    }
}

上下文初始化期间的打印输出是:

Bean 1 constructor
Bean 1 @PostConstruct started
Bean 2 constructor
Bean 2 @PostConstruct started
Bean 2 @PostConstruct completed
Bean 1 @PostConstruct completed

对于不同的getBean 方法,如果你传入一个类,那么该类的一个 bean 必须存在于应用程序上下文中(否则 Spring 不会不是你要求的那个类的多个 bean 实例中的哪一个),而通过名称搜索可以获取特定的命名 bean 实例。

【讨论】:

  • 你能找到官方文档支持“@PostConstruct 方法,在所有 bean 创建后调用。”基于它的 cmets,postConstruct 会在 THIS bean 被构造之后立即被调用。而且我认为,每个 bean 都是一个接一个地构建的。所以请提供更多证据:)
  • @Tiina 您似乎是对的,不能保证此时已创建未显式自动装配的 bean。我编辑了我的答案。
【解决方案2】:

首先,String 是一个完整的权限类,就像您可以自己创建的任何类一样。

您在 fooService 中得到一些东西的原因是 ApplicationContext getBean method 能够根据您传递给它的参数检索托管 bean。

如果无法检索 bean,您可能会遇到以下一些异常:

抛出:NoSuchBeanDefinitionException - 如果没有给定类型的 bean 发现 NoUniqueBeanDefinitionException - 如果有多个 bean 找到给定的类型 BeansException - 如果 bean 不能 已创建

【讨论】:

  • 但是如果一个 bean 没有被初始化,即没有被加载到上下文中,并且这个 bean 比 FooService bean 更早被初始化怎么办。这样,getBean 就会返回 null。
  • 这是真的吗,applicationContext.getBean(...) 就像 (at)Autowired 一样,如果 spring 可以找到它的定义,它会确保返回一个 bean?
  • 实际上 Autowired 更好,因为使用注解意味着更低的耦合度。
猜你喜欢
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-16
  • 2021-12-12
  • 2013-04-13
相关资源
最近更新 更多