@Test
  public void testFactoryMethodsSingletonOnTargetClass() {
    DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
    reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));

    TestBean tb = (TestBean) xbf.getBean("defaultTestBean");
    assertEquals("defaultInstance", tb.getName());
    assertEquals(1, tb.getAge());

    FactoryMethods fm = (FactoryMethods) xbf.getBean("default");
    assertEquals(0, fm.getNum());
    assertEquals("default", fm.getName());
    assertEquals("defaultInstance", fm.getTestBean().getName());
    assertEquals("setterString", fm.getStringValue());

    fm = (FactoryMethods) xbf.getBean("testBeanOnly");
    assertEquals(0, fm.getNum());
    assertEquals("default", fm.getName());
    // This comes from the test bean
    assertEquals("Juergen", fm.getTestBean().getName());

    fm = (FactoryMethods) xbf.getBean("full");
    assertEquals(27, fm.getNum());
    assertEquals("gotcha", fm.getName());
    assertEquals("Juergen", fm.getTestBean().getName());

    FactoryMethods fm2 = (FactoryMethods) xbf.getBean("full");
    assertSame(fm, fm2);

    xbf.destroySingletons();
    assertTrue(tb.wasDestroyed());
  }
  @Test
  public void testFactoryMethodsWithAutowire() {
    DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
    reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));

    FactoryMethods fm = (FactoryMethods) xbf.getBean("fullWithAutowire");
    assertEquals(27, fm.getNum());
    assertEquals("gotchaAutowired", fm.getName());
    assertEquals("Juergen", fm.getTestBean().getName());
  }
  @Test
  public void testCanSpecifyFactoryMethodArgumentsOnFactoryMethodPrototype() {
    DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
    reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
    TestBean tbArg = new TestBean();
    tbArg.setName("arg1");
    TestBean tbArg2 = new TestBean();
    tbArg2.setName("arg2");

    FactoryMethods fm1 = (FactoryMethods) xbf.getBean("testBeanOnlyPrototype", tbArg);
    assertEquals(0, fm1.getNum());
    assertEquals("default", fm1.getName());
    // This comes from the test bean
    assertEquals("arg1", fm1.getTestBean().getName());

    FactoryMethods fm2 = (FactoryMethods) xbf.getBean("testBeanOnlyPrototype", tbArg2);
    assertEquals("arg2", fm2.getTestBean().getName());
    assertEquals(fm1.getNum(), fm2.getNum());
    assertEquals(fm2.getStringValue(), "testBeanOnlyPrototypeDISetterString");
    assertEquals(fm2.getStringValue(), fm2.getStringValue());
    // The TestBean reference is resolved to a prototype in the factory
    assertSame(fm2.getTestBean(), fm2.getTestBean());
    assertNotSame(fm1, fm2);

    FactoryMethods fm3 =
        (FactoryMethods) xbf.getBean("testBeanOnlyPrototype", tbArg2, new Integer(1), "myName");
    assertEquals(1, fm3.getNum());
    assertEquals("myName", fm3.getName());
    assertEquals("arg2", fm3.getTestBean().getName());

    FactoryMethods fm4 = (FactoryMethods) xbf.getBean("testBeanOnlyPrototype", tbArg);
    assertEquals(0, fm4.getNum());
    assertEquals("default", fm4.getName());
    assertEquals("arg1", fm4.getTestBean().getName());
  }
  @Test
  public void testFactoryMethodsPrototypeOnTargetClass() {
    DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
    reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
    FactoryMethods fm = (FactoryMethods) xbf.getBean("defaultPrototype");
    FactoryMethods fm2 = (FactoryMethods) xbf.getBean("defaultPrototype");
    assertEquals(0, fm.getNum());
    assertEquals("default", fm.getName());
    assertEquals("defaultInstance", fm.getTestBean().getName());
    assertEquals("setterString", fm.getStringValue());
    assertEquals(fm.getNum(), fm2.getNum());
    assertEquals(fm.getStringValue(), fm2.getStringValue());
    // The TestBean is created separately for each bean
    assertNotSame(fm.getTestBean(), fm2.getTestBean());
    assertNotSame(fm, fm2);

    fm = (FactoryMethods) xbf.getBean("testBeanOnlyPrototype");
    fm2 = (FactoryMethods) xbf.getBean("testBeanOnlyPrototype");
    assertEquals(0, fm.getNum());
    assertEquals("default", fm.getName());
    // This comes from the test bean
    assertEquals("Juergen", fm.getTestBean().getName());
    assertEquals(fm.getNum(), fm2.getNum());
    assertEquals(fm.getStringValue(), fm2.getStringValue());
    // The TestBean reference is resolved to a prototype in the factory
    assertSame(fm.getTestBean(), fm2.getTestBean());
    assertNotSame(fm, fm2);

    fm = (FactoryMethods) xbf.getBean("fullPrototype");
    fm2 = (FactoryMethods) xbf.getBean("fullPrototype");
    assertEquals(27, fm.getNum());
    assertEquals("gotcha", fm.getName());
    assertEquals("Juergen", fm.getTestBean().getName());
    assertEquals(fm.getNum(), fm2.getNum());
    assertEquals(fm.getStringValue(), fm2.getStringValue());
    // The TestBean reference is resolved to a prototype in the factory
    assertSame(fm.getTestBean(), fm2.getTestBean());
    assertNotSame(fm, fm2);
  }