2015-08-30 134 views
2

我能夠測試在單例bean中自動裝配原型bean的結果是隻創建一個原型bean。使用AOP作用域代理自動裝入單例bean中的原型bean

作爲一個解決方案,我讀了我可以定義原型bean的AOP作用域代理或使用Spring的查找方法注入。

這是我曾嘗試 -

PrototypeBean.java

@Component 
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.INTERFACES) 
public class PrototypeBean implements Prototype { 

private String welcomeMessage; 

public String getWelcomeMessage() { 
    return welcomeMessage; 
} 

public void setWelcomeMessage(final String welcomeMessage) { 
    this.welcomeMessage = welcomeMessage; 
} 
} 

SingletonBean.java

@Component 
public class SingletonBean implements Singleton{ 
@Autowired private Prototype prototype; 

public Prototype getPrototype() { 
    return prototype; 
} 

public void greet() { 
    System.out.println(prototype.getWelcomeMessage()); 
} 
} 

測試類

public class AutowiredDependenciesDemo { 

@Autowired private Singleton autowiredSingleton; 
@Autowired ConfigurableApplicationContext context; 

@Test 
public void testPrototypeBeanWithAopScopedProxy(){ 
    Assert.assertNotNull(autowiredSingleton); 

    Prototype prototypeBean = (Prototype) ((SingletonBean) autowiredSingleton).getPrototype(); 
    prototypeBean.setWelcomeMessage("hello world"); 

    autowiredSingleton.greet(); 

    Singleton contextSingleton = (Singleton) context.getBean("singletonBean"); 
    Assert.assertSame(autowiredSingleton, contextSingleton); 

    Prototype anotherPrototypeBean = (Prototype) ((SingletonBean)contextSingleton).getPrototype(); 
    anotherPrototypeBean.setWelcomeMessage("hello india"); 

    contextSingleton.greet(); 
    autowiredSingleton.greet(); 
    // i expected both the prototype instances to be different. in the debugger, it does show two different 'proxied' instances. however the test fails. 
    Assert.assertNotSame(prototypeBean, anotherPrototypeBean); 
} 

我在這裏失去了一些東西?此外,對greet()方法的調用返回null。

回答

5

在思考代理和原型bean時,有些東西可以混合使用。

當Spring Framework將一個Prototype Scoped bean注入到Singleton Scoped bean中時,它創建一個Proxy對象(它實現了所有必需的接口)並注入它,而不是Prototype bean的實例。然後,無論何時在此Prototype Proxy上調用方法,Spring都將創建一個新實例,並在該新實例上調用該方法。

在你的案例中 - 在測試中 - 你只比較注入的代理,它們是相同的,因爲Prototype Bean只存在1個代理,並且此代理負責在需要時創建Prototype Bean的新實例。

這裏是我的例子: 我有一個接口Prototype和它的實現PrototypeImpl。在我的測試中,我直接從ApplicationContext獲取Prototype類型的bean,並且還使用@Autowired注入它。然後在調試器我看到:

enter image description here

注意,只有同一個代理(看它的地址),但調用「的toString()」在該代理表示PrototypeImpl對象的兩個不同的地址。其中顯示了我上面寫的。

編輯:關於非代理信息

要由M. Deinum延長評論,你可以從代理下列方式提取基礎對象:

Prototype extracted = null; 

if(AopUtils.isAopProxy(a) && a instanceof Advised) { 
    Object target = ((Advised)a).getTargetSource().getTarget(); 
    extracted = (Prototype) target; 
} 
+0

是的,我也看到了類似的情況。但是,我試圖調用Proxied bean上的特定方法。在我的測試類中,我調用了'prototypeBean.setWelcomeMessage(「hello world」);''和'anotherPrototypeBean.setWelcomeMessage(「hello india」);''我期望這會讓Spring創建兩個Prototype bean每PrototypeBeanImpl內存地址),但後來的Assert語句並沒有證實我的觀察結果。 – user3842182

+0

每次調用此代理將創建一個Prototype Scoped bean的新實例。如果你想獲得這樣的Prototype Scoped bean的實例並調用它的多個方法,那麼你應該使用Lookup Method方法。 –

+1

它仍然是相同的代理(如答案解釋)。如果您想比較生成的對象,則需要展開代理對象並獲取對象的基礎實際實例。\ –

相關問題