2014-10-29 17 views
2

這發生在我將@Configuration帶註釋的類進行子類化時,並將其饋送到AnnotationConfigApplicationContext爲什麼這個基於Java的Spring配置創建兩個單例bean的實例?

下面的這些類將總結該場景。這裏是full source

public class Bar {} 

public class Foo { 
    private Bar bar; 
    public Foo(Bar bar) { this.bar = bar; } 
    @Override public String toString() { 
     return super.toString() + "(" + bar + ")"; 
    } 
} 

@Configuration 
public class BaseAppConfig { 
    @Bean public Foo foo() { return new Foo(bar()); } 
    @Bean public Bar bar() { return new Bar(); } 
} 

/** Omitting @Configuration here */ 
public class AppConfig extends BaseAppConfig { 
    @Bean @Override public Bar bar() { return new Bar(); } 
} 

public class App { 
    public static void main(String[] args) { 
     try (AnnotationConfigApplicationContext ctx = new 
       AnnotationConfigApplicationContext(AppConfig.class)) { 
      System.out.println(ctx.getBean(Foo.class).toString()); 
      System.out.println(ctx.getBean(Bar.class).toString()); 
     } 
    } 
} 

這個打印兩種Bar情況下,我希望看到相同的情況下兩次:

[email protected]([email protected]) 
[email protected] 

回答

2

因爲你省略@Configuration註釋(因爲它是不@Inherited

/** Omitting @Configuration here */ 
public class AppConfig extends BaseAppConfig { 

指定類的AnnotationConfigApplicationContext

AnnotationConfigApplicationContext ctx = new 
      AnnotationConfigApplicationContext(AppConfig.class) 

標誌着它作爲一個普通類,不是@Configuration bean類。

這意味着@Bean方法在lite模式下運行。

@Configuration 班對比的語義bean的方法,「bean間引用」在精簡版模式下不支持。 相反,當一個@Bean-方法調用另一個@Bean-方法,方式爲精簡 模式時,該調用是標準的Java方法調用; Spring 不通過CGLIB代理攔截調用。這類似於 inter- @ Transactional方法調用,其中在代理模式下,Spring不會調用 截取調用--Spring只能在AspectJ模式下執行此操作。

強調我的。這意味着,這將bar()呼叫

return new Foo(bar()); 

其實只是再次調用bar(),它沒有返回創建的舊實例。

@Configuration作品有春天創建註解類的代理用於緩存由@Bean工廠方法返回的實例。由於您刪除了@Configuration,因此Spring不會應用此緩存,並且方法調用將正常工作,在您的情況下會返回一個新實例。

+0

指着我**模式**是真正的問題的答案。這解釋了一切。我在[@Bean文檔](http://docs.spring.io/spring/docs/4.1.1.RELEASE/javadoc-api/org/springframework/context/annotation/Bean.html)上找到了規範, – 2014-10-30 07:38:03

1

而不是使用直接Bar對象的創作,你應該使用的Spring bean管理:

@Configuration 
public class BaseAppConfig { 
    @Bean @Autowired public Foo foo(Bar bar) { return new Foo(bar); } 
    @Bean public Bar bar() { return new Bar(); } 
} 

查看spring reference瞭解詳情。

相關問題