2015-08-30 93 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

它仍然是相同的代理(如答案解释)。如果您想比较生成的对象,则需要展开代理对象并获取对象的基础实际实例。\ –

相关问题