@Test
 public void prototypeCreationIsFastEnough() {
   if (factoryLog.isTraceEnabled() || factoryLog.isDebugEnabled()) {
     // Skip this test: Trace logging blows the time limit.
     return;
   }
   GenericApplicationContext ac = new GenericApplicationContext();
   RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
   rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
   rbd.getConstructorArgumentValues().addGenericArgumentValue("#{systemProperties.name}");
   rbd.getPropertyValues().add("country", "#{systemProperties.country}");
   ac.registerBeanDefinition("test", rbd);
   ac.refresh();
   StopWatch sw = new StopWatch();
   sw.start("prototype");
   System.getProperties().put("name", "juergen");
   System.getProperties().put("country", "UK");
   try {
     for (int i = 0; i < 100000; i++) {
       TestBean tb = (TestBean) ac.getBean("test");
       assertEquals("juergen", tb.getName());
       assertEquals("UK", tb.getCountry());
     }
     sw.stop();
   } finally {
     System.getProperties().remove("country");
     System.getProperties().remove("name");
   }
   assertTrue(
       "Prototype creation took too long: " + sw.getTotalTimeMillis(),
       sw.getTotalTimeMillis() < 6000);
 }
  @Test
  public void prototypeCreationReevaluatesExpressions() {
    GenericApplicationContext ac = new GenericApplicationContext();
    AnnotationConfigUtils.registerAnnotationConfigProcessors(ac);
    RootBeanDefinition rbd = new RootBeanDefinition(PrototypeTestBean.class);
    rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
    rbd.getPropertyValues().add("country", "#{systemProperties.country}");
    rbd.getPropertyValues().add("country2", new TypedStringValue("#{systemProperties.country}"));
    ac.registerBeanDefinition("test", rbd);
    ac.refresh();

    try {
      System.getProperties().put("name", "juergen1");
      System.getProperties().put("country", "UK1");
      PrototypeTestBean tb = (PrototypeTestBean) ac.getBean("test");
      assertEquals("juergen1", tb.getName());
      assertEquals("UK1", tb.getCountry());
      assertEquals("UK1", tb.getCountry2());

      System.getProperties().put("name", "juergen2");
      System.getProperties().put("country", "UK2");
      tb = (PrototypeTestBean) ac.getBean("test");
      assertEquals("juergen2", tb.getName());
      assertEquals("UK2", tb.getCountry());
      assertEquals("UK2", tb.getCountry2());
    } finally {
      System.getProperties().remove("name");
      System.getProperties().remove("country");
    }
  }
	@Test
	public void testResourceInjectionWithResolvableDependencyType() {
		DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
		CommonAnnotationBeanPostProcessor bpp = new CommonAnnotationBeanPostProcessor();
		bpp.setBeanFactory(bf);
		bf.addBeanPostProcessor(bpp);
		RootBeanDefinition abd = new RootBeanDefinition(ExtendedResourceInjectionBean.class);
		abd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
		bf.registerBeanDefinition("annotatedBean", abd);
		RootBeanDefinition tbd = new RootBeanDefinition(TestBean.class);
		tbd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
		bf.registerBeanDefinition("testBean4", tbd);

		bf.registerResolvableDependency(BeanFactory.class, bf);
		bf.registerResolvableDependency(INestedTestBean.class, new ObjectFactory<Object>() {
			@Override
			public Object getObject() throws BeansException {
				return new NestedTestBean();
			}
		});

		PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
		Properties props = new Properties();
		props.setProperty("tb", "testBean4");
		ppc.setProperties(props);
		ppc.postProcessBeanFactory(bf);

		ExtendedResourceInjectionBean bean = (ExtendedResourceInjectionBean) bf.getBean("annotatedBean");
		INestedTestBean tb = bean.getTestBean6();
		assertNotNull(tb);

		ExtendedResourceInjectionBean anotherBean = (ExtendedResourceInjectionBean) bf.getBean("annotatedBean");
		assertNotSame(anotherBean, bean);
		assertNotSame(anotherBean.getTestBean6(), tb);

		String[] depBeans = bf.getDependenciesForBean("annotatedBean");
		assertEquals(1, depBeans.length);
		assertEquals("testBean4", depBeans[0]);
	}
	@Test
	public void testResourceInjectionWithPrototypes() {
		DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
		CommonAnnotationBeanPostProcessor bpp = new CommonAnnotationBeanPostProcessor();
		bpp.setResourceFactory(bf);
		bf.addBeanPostProcessor(bpp);
		RootBeanDefinition abd = new RootBeanDefinition(ResourceInjectionBean.class);
		abd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
		bf.registerBeanDefinition("annotatedBean", abd);
		RootBeanDefinition tbd1 = new RootBeanDefinition(TestBean.class);
		tbd1.setScope(BeanDefinition.SCOPE_PROTOTYPE);
		bf.registerBeanDefinition("testBean", tbd1);
		RootBeanDefinition tbd2 = new RootBeanDefinition(TestBean.class);
		tbd2.setScope(BeanDefinition.SCOPE_PROTOTYPE);
		bf.registerBeanDefinition("testBean2", tbd2);

		ResourceInjectionBean bean = (ResourceInjectionBean) bf.getBean("annotatedBean");
		assertTrue(bean.initCalled);
		assertTrue(bean.init2Called);
		assertTrue(bean.init3Called);

		TestBean tb = bean.getTestBean();
		TestBean tb2 = bean.getTestBean2();
		assertNotNull(tb);
		assertNotNull(tb2);

		ResourceInjectionBean anotherBean = (ResourceInjectionBean) bf.getBean("annotatedBean");
		assertNotSame(anotherBean, bean);
		assertNotSame(anotherBean.getTestBean(), tb);
		assertNotSame(anotherBean.getTestBean2(), tb2);

		bf.destroyBean("annotatedBean", bean);
		assertTrue(bean.destroyCalled);
		assertTrue(bean.destroy2Called);
		assertTrue(bean.destroy3Called);
	}
  public void testSerializability() throws Exception {
    MutablePropertyValues tsPvs = new MutablePropertyValues();
    tsPvs.addPropertyValue("targetBeanName", "person");
    RootBeanDefinition tsBd = new RootBeanDefinition(TestTargetSource.class, tsPvs);

    MutablePropertyValues pvs = new MutablePropertyValues();
    RootBeanDefinition bd = new RootBeanDefinition(SerializablePerson.class, pvs);
    bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);

    DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
    bf.registerBeanDefinition("ts", tsBd);
    bf.registerBeanDefinition("person", bd);

    TestTargetSource cpts = (TestTargetSource) bf.getBean("ts");
    TargetSource serialized = (TargetSource) SerializationTestUtils.serializeAndDeserialize(cpts);
    assertTrue(
        "Changed to SingletonTargetSource on deserialization",
        serialized instanceof SingletonTargetSource);
    SingletonTargetSource sts = (SingletonTargetSource) serialized;
    assertNotNull(sts.getTarget());
  }
 @Override
 public Object buildBean(String beanName, Map<String, Object> extraContext) throws Exception {
   LOG.debug("Building bean for name {}", beanName);
   if (!skipBeanNames.contains(beanName)) {
     ApplicationContext anAppContext = getApplicationContext(extraContext);
     try {
       LOG.debug(
           "Trying the application context... appContext = {},\n bean name = {}",
           anAppContext,
           beanName);
       return anAppContext.getBean(beanName);
     } catch (NoSuchBeanDefinitionException e) {
       LOG.debug(
           "Did not find bean definition for bean named {}, creating a new one...", beanName);
       if (autoWiringFactory instanceof BeanDefinitionRegistry) {
         try {
           Class clazz = Class.forName(beanName);
           BeanDefinitionRegistry registry = (BeanDefinitionRegistry) autoWiringFactory;
           RootBeanDefinition def = new RootBeanDefinition(clazz, autowireStrategy, true);
           def.setScope(BeanDefinition.SCOPE_SINGLETON);
           LOG.debug("Registering a new bean definition for class {}", beanName);
           registry.registerBeanDefinition(beanName, def);
           try {
             return anAppContext.getBean(beanName);
           } catch (NoSuchBeanDefinitionException e2) {
             LOG.warn("Could not register new bean definition for bean {}", beanName);
             skipBeanNames.add(beanName);
           }
         } catch (ClassNotFoundException e1) {
           skipBeanNames.add(beanName);
         }
       }
     }
   }
   LOG.debug("Returning autowired instance created by default ObjectFactory");
   return autoWireBean(super.buildBean(beanName, extraContext), autoWiringFactory);
 }
  @Test
  public void nonSingletonListenerInApplicationContext() {
    StaticApplicationContext context = new StaticApplicationContext();
    RootBeanDefinition listener = new RootBeanDefinition(MyNonSingletonListener.class);
    listener.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
    context.registerBeanDefinition("listener", listener);
    context.refresh();

    MyEvent event1 = new MyEvent(context);
    context.publishEvent(event1);
    MyOtherEvent event2 = new MyOtherEvent(context);
    context.publishEvent(event2);
    MyEvent event3 = new MyEvent(context);
    context.publishEvent(event3);
    MyOtherEvent event4 = new MyOtherEvent(context);
    context.publishEvent(event4);
    assertTrue(MyNonSingletonListener.seenEvents.contains(event1));
    assertTrue(MyNonSingletonListener.seenEvents.contains(event2));
    assertTrue(MyNonSingletonListener.seenEvents.contains(event3));
    assertTrue(MyNonSingletonListener.seenEvents.contains(event4));
    MyNonSingletonListener.seenEvents.clear();

    context.close();
  }
  /**
   * Read a particular {@link ConfigurationClassMethod}, registering bean definitions with the
   * BeanDefinitionRegistry based on its contents.
   */
  private void loadBeanDefinitionsForBeanMethod(ConfigurationClassMethod beanMethod) {
    ConfigurationClass configClass = beanMethod.getConfigurationClass();
    MethodMetadata metadata = beanMethod.getMetadata();

    RootBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass);
    beanDef.setResource(configClass.getResource());
    beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
    beanDef.setFactoryBeanName(configClass.getBeanName());
    beanDef.setUniqueFactoryMethodName(metadata.getMethodName());
    beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
    beanDef.setAttribute(
        RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);

    // consider name and any aliases
    Map<String, Object> beanAttributes = metadata.getAnnotationAttributes(Bean.class.getName());
    List<String> names =
        new ArrayList<String>(Arrays.asList((String[]) beanAttributes.get("name")));
    String beanName =
        (names.size() > 0 ? names.remove(0) : beanMethod.getMetadata().getMethodName());
    for (String alias : names) {
      this.registry.registerAlias(beanName, alias);
    }

    // has this already been overridden (e.g. via XML)?
    if (this.registry.containsBeanDefinition(beanName)) {
      BeanDefinition existingBeanDef = registry.getBeanDefinition(beanName);
      // is the existing bean definition one that was created from a configuration class?
      if (!(existingBeanDef instanceof ConfigurationClassBeanDefinition)) {
        // no -> then it's an external override, probably XML
        // overriding is legal, return immediately
        if (logger.isDebugEnabled()) {
          logger.debug(
              String.format(
                  "Skipping loading bean definition for %s: a definition for bean "
                      + "'%s' already exists. This is likely due to an override in XML.",
                  beanMethod, beanName));
        }
        return;
      }
    }

    if (metadata.isAnnotated(Primary.class.getName())) {
      beanDef.setPrimary(true);
    }

    // is this bean to be instantiated lazily?
    if (metadata.isAnnotated(Lazy.class.getName())) {
      beanDef.setLazyInit(
          (Boolean) metadata.getAnnotationAttributes(Lazy.class.getName()).get("value"));
    } else if (configClass.getMetadata().isAnnotated(Lazy.class.getName())) {
      beanDef.setLazyInit(
          (Boolean)
              configClass.getMetadata().getAnnotationAttributes(Lazy.class.getName()).get("value"));
    }

    if (metadata.isAnnotated(DependsOn.class.getName())) {
      String[] dependsOn =
          (String[]) metadata.getAnnotationAttributes(DependsOn.class.getName()).get("value");
      if (dependsOn.length > 0) {
        beanDef.setDependsOn(dependsOn);
      }
    }

    Autowire autowire = (Autowire) beanAttributes.get("autowire");
    if (autowire.isAutowire()) {
      beanDef.setAutowireMode(autowire.value());
    }

    String initMethodName = (String) beanAttributes.get("initMethod");
    if (StringUtils.hasText(initMethodName)) {
      beanDef.setInitMethodName(initMethodName);
    }

    String destroyMethodName = (String) beanAttributes.get("destroyMethod");
    if (StringUtils.hasText(destroyMethodName)) {
      beanDef.setDestroyMethodName(destroyMethodName);
    }

    // consider scoping
    ScopedProxyMode proxyMode = ScopedProxyMode.NO;
    Map<String, Object> scopeAttributes = metadata.getAnnotationAttributes(Scope.class.getName());
    if (scopeAttributes != null) {
      beanDef.setScope((String) scopeAttributes.get("value"));
      proxyMode = (ScopedProxyMode) scopeAttributes.get("proxyMode");
      if (proxyMode == ScopedProxyMode.DEFAULT) {
        proxyMode = ScopedProxyMode.NO;
      }
    }

    // replace the original bean definition with the target one, if necessary
    BeanDefinition beanDefToRegister = beanDef;
    if (proxyMode != ScopedProxyMode.NO) {
      BeanDefinitionHolder proxyDef =
          ScopedProxyCreator.createScopedProxy(
              new BeanDefinitionHolder(beanDef, beanName),
              this.registry,
              proxyMode == ScopedProxyMode.TARGET_CLASS);
      beanDefToRegister = proxyDef.getBeanDefinition();
    }

    if (logger.isDebugEnabled()) {
      logger.debug(
          String.format(
              "Registering bean definition for @Bean method %s.%s()",
              configClass.getMetadata().getClassName(), beanName));
    }

    registry.registerBeanDefinition(beanName, beanDefToRegister);
  }