2016-11-17 116 views
2

下面的代码在春季4中工作正常,但我想知道为什么getBean(FooService.class)返回一个已经加载的bean。我认为bean的加载顺序不能保证,这意味着可能会得到一个空bean。这是因为加载目标是一个类而不是一个字符串(即对象)还是因为FooService bean有一个特殊的范围,如原型?如果是这样,是什么的getBean(类)和的getBean(对象)为什么这个bean不为空

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); 
    } 
+0

我认为这是春天的感觉,不得空对象 – XtremeBaumer

+0

其实我认为你的* bean *是** null **,我的意思是,你使用* applicationContext *来加载特定的bean对象。有了春天,你不需要它。您可以在bean参数上使用* @ Autowired *注解,或者在bean是参数的类构造函数中或在* set *方法中更好地使用* @ Autowired *注释。 –

回答

0

对于初学者之间的区别,String是一个充分的权利类,像任何你可以自己创建。

您在fooService中获取某些内容的原因是ApplicationContext getBean method能够根据您传递给它的参数来检索托管bean。

如果它无法获取豆,你可以得到一些例外:

抛出:NoSuchBeanDefinitionException - 如果没有给定类型 的豆发现NoUniqueBeanDefinitionException - 如果超过一个豆的 给定类型被发现BeansException - 如果bean不能 创建如果尚未已经创建它

+0

但是如果一个bean没有被初始化,即没有加载到上下文中,并且这个bean被初始化的时间早于FooService bean。这样,getBean将返回null。 – Tiina

+0

请参阅我的编辑。 – Andres

+0

这是真的,applicationContext.getBean(...)就像(自动装配的),Spring会确保返回一个bean,如果它能找到它的定义? – Tiina

1

ApplicationContext::getBean方法创建指定类型的豆。

为以下两个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方法,如果在一类通过,则正好一个豆该类必须存在于应用程序上下文中(否则Spring不会为你要求的那个类的多个bean实例中的哪一个),而按名称搜索允许你获得一个特定的命名bean实例。

+0

您能否找到官方文档支持“@PostConstruct方法,该方法在所有bean创建完成后调用”。基于它的注释,postConstruct在THIS bean构建完成后立即被调用。我认为,每个bean都是一个接一个地构建的。所以多一点证据请:) – Tiina

+0

@Tiina你似乎是对的,不能保证没有明确自动布线的bean现在已经被创建。我编辑了我的答案。 –

+0

@Dragon Bozanovic很清楚。 :) – Tiina