/**
  * Create a Spring {@link ConfigurableApplicationContext} for use by this test.
  *
  * <p>The default implementation creates a standard {@link GenericApplicationContext} instance,
  * calls the {@link #prepareApplicationContext} prepareApplicationContext} method and the {@link
  * #customizeBeanFactory customizeBeanFactory} method to allow for customizing the context and its
  * DefaultListableBeanFactory, populates the context from the specified config {@code locations}
  * through the configured {@link #createBeanDefinitionReader(GenericApplicationContext)
  * BeanDefinitionReader}, and finally {@link ConfigurableApplicationContext#refresh() refreshes}
  * the context.
  *
  * @param locations the config locations (as Spring resource locations, e.g. full classpath
  *     locations or any kind of URL)
  * @return the GenericApplicationContext instance
  * @see #loadContext(String...)
  * @see #customizeBeanFactory(DefaultListableBeanFactory)
  * @see #createBeanDefinitionReader(GenericApplicationContext)
  */
 private ConfigurableApplicationContext createApplicationContext(String... locations) {
   GenericApplicationContext context = new GenericApplicationContext();
   new XmlBeanDefinitionReader(context).loadBeanDefinitions(locations);
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   context.refresh();
   return context;
 }
  @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
     testAutowiredFieldDoesNotResolveWithMultipleQualifierValuesAndMultipleMatchingCandidates() {
   GenericApplicationContext context = new GenericApplicationContext();
   ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
   cavs1.addGenericArgumentValue(JUERGEN);
   RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
   AutowireCandidateQualifier qualifier =
       new AutowireCandidateQualifier(TestQualifierWithMultipleAttributes.class);
   qualifier.setAttribute("number", 123);
   person1.addQualifier(qualifier);
   ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
   cavs2.addGenericArgumentValue(MARK);
   RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
   AutowireCandidateQualifier qualifier2 =
       new AutowireCandidateQualifier(TestQualifierWithMultipleAttributes.class);
   qualifier2.setAttribute("number", 123);
   qualifier2.setAttribute("value", "default");
   person2.addQualifier(qualifier2);
   context.registerBeanDefinition(JUERGEN, person1);
   context.registerBeanDefinition(MARK, person2);
   context.registerBeanDefinition(
       "autowired", new RootBeanDefinition(QualifiedFieldWithMultipleAttributesTestBean.class));
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   try {
     context.refresh();
     fail("expected BeanCreationException");
   } catch (BeanCreationException e) {
     assertTrue(e.getRootCause() instanceof NoSuchBeanDefinitionException);
     assertEquals("autowired", e.getBeanName());
   }
 }
 @Test
 public void
     testAutowiredFieldDoesNotResolveWithBaseQualifierAndNonDefaultValueAndMultipleMatchingCandidates() {
   GenericApplicationContext context = new GenericApplicationContext();
   ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
   cavs1.addGenericArgumentValue("the real juergen");
   RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
   person1.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "juergen"));
   ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
   cavs2.addGenericArgumentValue("juergen imposter");
   RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
   person2.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "juergen"));
   context.registerBeanDefinition("juergen1", person1);
   context.registerBeanDefinition("juergen2", person2);
   context.registerBeanDefinition(
       "autowired",
       new RootBeanDefinition(
           QualifiedConstructorArgumentWithBaseQualifierNonDefaultValueTestBean.class));
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   try {
     context.refresh();
     fail("expected BeanCreationException");
   } catch (BeanCreationException e) {
     assertTrue(e instanceof UnsatisfiedDependencyException);
     assertEquals("autowired", e.getBeanName());
   }
 }
  /**
   * Load a Spring {@link WebApplicationContext} from the supplied {@link
   * MergedContextConfiguration}.
   *
   * <p>Implementation details:
   *
   * <ul>
   *   <li>Creates a {@link GenericWebApplicationContext} instance.
   *   <li>Delegates to {@link #configureWebResources} to create the {@link MockServletContext} and
   *       set it in the {@code WebApplicationContext}.
   *   <li>Calls {@link #prepareContext} to allow for customizing the context before bean
   *       definitions are loaded.
   *   <li>Calls {@link #customizeBeanFactory} to allow for customizing the context's {@code
   *       DefaultListableBeanFactory}.
   *   <li>Delegates to {@link #loadBeanDefinitions} to populate the context from the locations or
   *       classes in the supplied {@code MergedContextConfiguration}.
   *   <li>Delegates to {@link AnnotationConfigUtils} for {@linkplain
   *       AnnotationConfigUtils#registerAnnotationConfigProcessors registering} annotation
   *       configuration processors.
   *   <li>Calls {@link #customizeContext} to allow for customizing the context before it is
   *       refreshed.
   *   <li>{@link ConfigurableApplicationContext#refresh Refreshes} the context and registers a JVM
   *       shutdown hook for it.
   * </ul>
   *
   * @return a new web application context
   * @see
   *     org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration)
   * @see GenericWebApplicationContext
   */
  @Override
  public final ConfigurableApplicationContext loadContext(MergedContextConfiguration mergedConfig)
      throws Exception {

    if (!(mergedConfig instanceof WebMergedContextConfiguration)) {
      throw new IllegalArgumentException(
          String.format(
              "Cannot load WebApplicationContext from non-web merged context configuration %s. "
                  + "Consider annotating your test class with @WebAppConfiguration.",
              mergedConfig));
    }
    WebMergedContextConfiguration webMergedConfig = (WebMergedContextConfiguration) mergedConfig;

    if (logger.isDebugEnabled()) {
      logger.debug(
          String.format(
              "Loading WebApplicationContext for merged context configuration %s.",
              webMergedConfig));
    }

    GenericWebApplicationContext context = new GenericWebApplicationContext();
    configureWebResources(context, webMergedConfig);
    prepareContext(context, webMergedConfig);
    customizeBeanFactory(context.getDefaultListableBeanFactory(), webMergedConfig);
    loadBeanDefinitions(context, webMergedConfig);
    AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
    customizeContext(context, webMergedConfig);
    context.refresh();
    context.registerShutdownHook();
    return context;
  }
 @Test
 public void
     testAutowiredFieldDoesNotResolveCandidateWithDefaultValueAndConflictingValueOnBeanDefinition() {
   GenericApplicationContext context = new GenericApplicationContext();
   ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
   cavs1.addGenericArgumentValue(JUERGEN);
   RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
   // qualifier added, and non-default value specified
   person1.addQualifier(
       new AutowireCandidateQualifier(TestQualifierWithDefaultValue.class, "not the default"));
   ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
   cavs2.addGenericArgumentValue(MARK);
   RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
   context.registerBeanDefinition(JUERGEN, person1);
   context.registerBeanDefinition(MARK, person2);
   context.registerBeanDefinition(
       "autowired", new RootBeanDefinition(QualifiedFieldWithDefaultValueTestBean.class));
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   try {
     context.refresh();
     fail("expected BeanCreationException");
   } catch (BeanCreationException e) {
     assertTrue(e.getRootCause() instanceof NoSuchBeanDefinitionException);
     assertEquals("autowired", e.getBeanName());
   }
 }
 @Test
 public void testAutowiredFieldResolvesWithMultipleQualifierValuesAndExplicitDefaultValue() {
   GenericApplicationContext context = new GenericApplicationContext();
   ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
   cavs1.addGenericArgumentValue(JUERGEN);
   RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
   AutowireCandidateQualifier qualifier =
       new AutowireCandidateQualifier(TestQualifierWithMultipleAttributes.class);
   qualifier.setAttribute("number", 456);
   person1.addQualifier(qualifier);
   ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
   cavs2.addGenericArgumentValue(MARK);
   RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
   AutowireCandidateQualifier qualifier2 =
       new AutowireCandidateQualifier(TestQualifierWithMultipleAttributes.class);
   qualifier2.setAttribute("number", 123);
   qualifier2.setAttribute("value", "default");
   person2.addQualifier(qualifier2);
   context.registerBeanDefinition(JUERGEN, person1);
   context.registerBeanDefinition(MARK, person2);
   context.registerBeanDefinition(
       "autowired", new RootBeanDefinition(QualifiedFieldWithMultipleAttributesTestBean.class));
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   context.refresh();
   QualifiedFieldWithMultipleAttributesTestBean bean =
       (QualifiedFieldWithMultipleAttributesTestBean) context.getBean("autowired");
   assertEquals(MARK, bean.getPerson().getName());
 }
 @Test
 public void testAutowiredFieldWithSingleQualifiedCandidate() {
   GenericApplicationContext context = new GenericApplicationContext();
   ConstructorArgumentValues cavs = new ConstructorArgumentValues();
   cavs.addGenericArgumentValue(JUERGEN);
   RootBeanDefinition person = new RootBeanDefinition(Person.class, cavs, null);
   person.addQualifier(new AutowireCandidateQualifier(TestQualifier.class));
   context.registerBeanDefinition(JUERGEN, person);
   context.registerBeanDefinition(
       "autowired", new RootBeanDefinition(QualifiedFieldTestBean.class));
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   context.refresh();
   QualifiedFieldTestBean bean = (QualifiedFieldTestBean) context.getBean("autowired");
   assertEquals(JUERGEN, bean.getPerson().getName());
 }
  @Test
  public void stringConcatenationWithDebugLogging() {
    GenericApplicationContext ac = new GenericApplicationContext();
    AnnotationConfigUtils.registerAnnotationConfigProcessors(ac);

    GenericBeanDefinition bd = new GenericBeanDefinition();
    bd.setBeanClass(String.class);
    bd.getConstructorArgumentValues()
        .addGenericArgumentValue("test-#{ T(java.lang.System).currentTimeMillis() }");
    ac.registerBeanDefinition("str", bd);
    ac.refresh();

    String str = ac.getBean("str", String.class);
    assertTrue(str.startsWith("test-"));
  }
 public ApplicationContext loadContext(String... locations) throws Exception {
   if (logger.isDebugEnabled()) {
     logger.debug(
         "Loading ApplicationContext for locations ["
             + StringUtils.arrayToCommaDelimitedString(locations)
             + "].");
   }
   GenericWebApplicationContext context = new GenericWebApplicationContext();
   prepareContext(context);
   customizeBeanFactory(context.getDefaultListableBeanFactory());
   createBeanDefinitionReader(context).loadBeanDefinitions(locations);
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   customizeContext(context);
   context.refresh();
   context.registerShutdownHook();
   return context;
 }
 @Test
 public void testAutowiredMethodParameterWithStaticallyQualifiedCandidate() {
   GenericApplicationContext context = new GenericApplicationContext();
   ConstructorArgumentValues cavs = new ConstructorArgumentValues();
   cavs.addGenericArgumentValue(JUERGEN);
   RootBeanDefinition person = new RootBeanDefinition(QualifiedPerson.class, cavs, null);
   context.registerBeanDefinition(
       JUERGEN,
       ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(person, JUERGEN), context, true)
           .getBeanDefinition());
   context.registerBeanDefinition(
       "autowired", new RootBeanDefinition(QualifiedMethodParameterTestBean.class));
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   context.refresh();
   QualifiedMethodParameterTestBean bean =
       (QualifiedMethodParameterTestBean) context.getBean("autowired");
   assertEquals(JUERGEN, bean.getPerson().getName());
 }
 @Test
 public void testAutowiredConstructorArgumentWithSingleNonQualifiedCandidate() {
   GenericApplicationContext context = new GenericApplicationContext();
   ConstructorArgumentValues cavs = new ConstructorArgumentValues();
   cavs.addGenericArgumentValue(JUERGEN);
   RootBeanDefinition person = new RootBeanDefinition(Person.class, cavs, null);
   context.registerBeanDefinition(JUERGEN, person);
   context.registerBeanDefinition(
       "autowired", new RootBeanDefinition(QualifiedConstructorArgumentTestBean.class));
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   try {
     context.refresh();
     fail("expected BeanCreationException");
   } catch (BeanCreationException e) {
     assertTrue(e instanceof UnsatisfiedDependencyException);
     assertEquals("autowired", e.getBeanName());
   }
 }
 @Test
 public void testAutowiredMethodParameterWithStaticallyQualifiedCandidateAmongOthers() {
   GenericApplicationContext context = new GenericApplicationContext();
   ConstructorArgumentValues cavs = new ConstructorArgumentValues();
   cavs.addGenericArgumentValue(JUERGEN);
   RootBeanDefinition person = new RootBeanDefinition(QualifiedPerson.class, cavs, null);
   ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
   cavs2.addGenericArgumentValue(MARK);
   RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
   context.registerBeanDefinition(JUERGEN, person);
   context.registerBeanDefinition(MARK, person2);
   context.registerBeanDefinition(
       "autowired", new RootBeanDefinition(QualifiedMethodParameterTestBean.class));
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   context.refresh();
   QualifiedMethodParameterTestBean bean =
       (QualifiedMethodParameterTestBean) context.getBean("autowired");
   assertEquals(JUERGEN, bean.getPerson().getName());
 }
  public ApplicationContext loadContext(MergedContextConfiguration config) throws Exception {
    GenericWebApplicationContext context = new GenericWebApplicationContext();

    // Commented out until SPR-10392 is fixed and we can upgrade to Spring 3.2.3.RELEASE or higher
    //		ApplicationContext parent = config.getParentApplicationContext();
    //		if(parent != null) {
    //			context.setParent(parent);
    //		}

    prepareContext(context);
    prepareContext(context, config);
    customizeBeanFactory(context.getDefaultListableBeanFactory());
    createBeanDefinitionReader(context).loadBeanDefinitions(config.getLocations());
    AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
    customizeContext(context);
    context.refresh();
    context.registerShutdownHook();

    return context;
  }
 @Test
 public void testAutowiredFieldResolvesWithDefaultValueAndExplicitDefaultValueOnBeanDefinition() {
   GenericApplicationContext context = new GenericApplicationContext();
   ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
   cavs1.addGenericArgumentValue(JUERGEN);
   RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
   // qualifier added, and value matches the default
   person1.addQualifier(
       new AutowireCandidateQualifier(TestQualifierWithDefaultValue.class, "default"));
   ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
   cavs2.addGenericArgumentValue(MARK);
   RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
   context.registerBeanDefinition(JUERGEN, person1);
   context.registerBeanDefinition(MARK, person2);
   context.registerBeanDefinition(
       "autowired", new RootBeanDefinition(QualifiedFieldWithDefaultValueTestBean.class));
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   context.refresh();
   QualifiedFieldWithDefaultValueTestBean bean =
       (QualifiedFieldWithDefaultValueTestBean) context.getBean("autowired");
   assertEquals(JUERGEN, bean.getPerson().getName());
 }
 @Test
 public void testAutowiredMethodParameterWithMultipleNonQualifiedCandidates() {
   GenericApplicationContext context = new GenericApplicationContext();
   ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
   cavs1.addGenericArgumentValue(JUERGEN);
   RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
   ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
   cavs2.addGenericArgumentValue(MARK);
   RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
   context.registerBeanDefinition(JUERGEN, person1);
   context.registerBeanDefinition(MARK, person2);
   context.registerBeanDefinition(
       "autowired", new RootBeanDefinition(QualifiedMethodParameterTestBean.class));
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   try {
     context.refresh();
     fail("expected BeanCreationException");
   } catch (BeanCreationException e) {
     assertTrue(e.getRootCause() instanceof NoSuchBeanDefinitionException);
     assertEquals("autowired", e.getBeanName());
   }
 }
  @Test
  public void systemPropertiesSecurityManager() {
    GenericApplicationContext ac = new GenericApplicationContext();
    AnnotationConfigUtils.registerAnnotationConfigProcessors(ac);

    GenericBeanDefinition bd = new GenericBeanDefinition();
    bd.setBeanClass(TestBean.class);
    bd.getPropertyValues().add("country", "#{systemProperties.country}");
    ac.registerBeanDefinition("tb", bd);

    SecurityManager oldSecurityManager = System.getSecurityManager();
    try {
      System.setProperty("country", "NL");

      SecurityManager securityManager =
          new SecurityManager() {
            @Override
            public void checkPropertiesAccess() {
              throw new AccessControlException("Not Allowed");
            }

            @Override
            public void checkPermission(Permission perm) {
              // allow everything else
            }
          };
      System.setSecurityManager(securityManager);
      ac.refresh();

      TestBean tb = ac.getBean("tb", TestBean.class);
      assertEquals("NL", tb.getCountry());

    } finally {
      System.setSecurityManager(oldSecurityManager);
      System.getProperties().remove("country");
    }
  }
  private void doTestJaxWsPortAccess(Object... features) throws Exception {
    GenericApplicationContext ac = new GenericApplicationContext();

    GenericBeanDefinition serviceDef = new GenericBeanDefinition();
    serviceDef.setBeanClass(OrderServiceImpl.class);
    ac.registerBeanDefinition("service", serviceDef);

    GenericBeanDefinition exporterDef = new GenericBeanDefinition();
    exporterDef.setBeanClass(SimpleJaxWsServiceExporter.class);
    exporterDef.getPropertyValues().add("baseAddress", "http://localhost:9999/");
    ac.registerBeanDefinition("exporter", exporterDef);

    GenericBeanDefinition clientDef = new GenericBeanDefinition();
    clientDef.setBeanClass(JaxWsPortProxyFactoryBean.class);
    clientDef.getPropertyValues().add("wsdlDocumentUrl", "http://localhost:9999/OrderService?wsdl");
    clientDef.getPropertyValues().add("namespaceUri", "http://jaxws.remoting.springframework.org/");
    clientDef.getPropertyValues().add("username", "juergen");
    clientDef.getPropertyValues().add("password", "hoeller");
    clientDef.getPropertyValues().add("serviceName", "OrderService");
    clientDef.getPropertyValues().add("serviceInterface", OrderService.class);
    clientDef.getPropertyValues().add("lookupServiceOnStartup", Boolean.FALSE);
    if (features != null) {
      clientDef.getPropertyValues().add("webServiceFeatures", features);
    }
    ac.registerBeanDefinition("client", clientDef);

    GenericBeanDefinition serviceFactoryDef = new GenericBeanDefinition();
    serviceFactoryDef.setBeanClass(LocalJaxWsServiceFactoryBean.class);
    serviceFactoryDef
        .getPropertyValues()
        .add("wsdlDocumentUrl", "http://localhost:9999/OrderService?wsdl");
    serviceFactoryDef
        .getPropertyValues()
        .add("namespaceUri", "http://jaxws.remoting.springframework.org/");
    serviceFactoryDef.getPropertyValues().add("serviceName", "OrderService");
    ac.registerBeanDefinition("orderService", serviceFactoryDef);

    ac.registerBeanDefinition("accessor", new RootBeanDefinition(ServiceAccessor.class));
    AnnotationConfigUtils.registerAnnotationConfigProcessors(ac);

    try {
      ac.refresh();

      OrderService orderService = ac.getBean("client", OrderService.class);
      assertTrue(orderService instanceof BindingProvider);
      ((BindingProvider) orderService).getRequestContext();

      String order = orderService.getOrder(1000);
      assertEquals("order 1000", order);
      try {
        orderService.getOrder(0);
        fail("Should have thrown OrderNotFoundException");
      } catch (OrderNotFoundException ex) {
        // expected
      }

      ServiceAccessor serviceAccessor = ac.getBean("accessor", ServiceAccessor.class);
      order = serviceAccessor.orderService.getOrder(1000);
      assertEquals("order 1000", order);
      try {
        serviceAccessor.orderService.getOrder(0);
        fail("Should have thrown OrderNotFoundException");
      } catch (OrderNotFoundException ex) {
        // expected
      }
    } catch (BeanCreationException ex) {
      if ("exporter".equals(ex.getBeanName())
          && ex.getRootCause() instanceof ClassNotFoundException) {
        // ignore - probably running on JDK < 1.6 without the JAX-WS impl present
      } else {
        throw ex;
      }
    } finally {
      ac.close();
    }
  }
  @Test
  public void genericApplicationContext() throws Exception {
    GenericApplicationContext ac = new GenericApplicationContext();
    AnnotationConfigUtils.registerAnnotationConfigProcessors(ac);

    ac.getBeanFactory()
        .registerScope(
            "myScope",
            new Scope() {
              public Object get(String name, ObjectFactory objectFactory) {
                return objectFactory.getObject();
              }

              public Object remove(String name) {
                return null;
              }

              public void registerDestructionCallback(String name, Runnable callback) {}

              public Object resolveContextualObject(String key) {
                if (key.equals("mySpecialAttr")) {
                  return "42";
                } else {
                  return null;
                }
              }

              public String getConversationId() {
                return null;
              }
            });

    PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
    Properties placeholders = new Properties();
    placeholders.setProperty("code", "123");
    ppc.setProperties(placeholders);
    ac.addBeanFactoryPostProcessor(ppc);

    GenericBeanDefinition bd0 = new GenericBeanDefinition();
    bd0.setBeanClass(TestBean.class);
    bd0.getPropertyValues().add("name", "myName");
    bd0.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "original"));
    ac.registerBeanDefinition("tb0", bd0);

    GenericBeanDefinition bd1 = new GenericBeanDefinition();
    bd1.setBeanClass(TestBean.class);
    bd1.setScope("myScope");
    bd1.getConstructorArgumentValues()
        .addGenericArgumentValue("XXX#{tb0.name}YYY#{mySpecialAttr}ZZZ");
    bd1.getConstructorArgumentValues().addGenericArgumentValue("#{mySpecialAttr}");
    ac.registerBeanDefinition("tb1", bd1);

    GenericBeanDefinition bd2 = new GenericBeanDefinition();
    bd2.setBeanClass(TestBean.class);
    bd2.setScope("myScope");
    bd2.getPropertyValues().add("name", "{ XXX#{tb0.name}YYY#{mySpecialAttr}ZZZ }");
    bd2.getPropertyValues().add("age", "#{mySpecialAttr}");
    bd2.getPropertyValues().add("country", "${code} #{systemProperties.country}");
    ac.registerBeanDefinition("tb2", bd2);

    GenericBeanDefinition bd3 = new GenericBeanDefinition();
    bd3.setBeanClass(ValueTestBean.class);
    bd3.setScope("myScope");
    ac.registerBeanDefinition("tb3", bd3);

    GenericBeanDefinition bd4 = new GenericBeanDefinition();
    bd4.setBeanClass(ConstructorValueTestBean.class);
    bd4.setScope("myScope");
    ac.registerBeanDefinition("tb4", bd4);

    GenericBeanDefinition bd5 = new GenericBeanDefinition();
    bd5.setBeanClass(MethodValueTestBean.class);
    bd5.setScope("myScope");
    ac.registerBeanDefinition("tb5", bd5);

    GenericBeanDefinition bd6 = new GenericBeanDefinition();
    bd6.setBeanClass(PropertyValueTestBean.class);
    bd6.setScope("myScope");
    ac.registerBeanDefinition("tb6", bd6);

    System.getProperties().put("country", "UK");
    try {
      ac.refresh();

      TestBean tb0 = ac.getBean("tb0", TestBean.class);

      TestBean tb1 = ac.getBean("tb1", TestBean.class);
      assertEquals("XXXmyNameYYY42ZZZ", tb1.getName());
      assertEquals(42, tb1.getAge());

      TestBean tb2 = ac.getBean("tb2", TestBean.class);
      assertEquals("{ XXXmyNameYYY42ZZZ }", tb2.getName());
      assertEquals(42, tb2.getAge());
      assertEquals("123 UK", tb2.getCountry());

      ValueTestBean tb3 = ac.getBean("tb3", ValueTestBean.class);
      assertEquals("XXXmyNameYYY42ZZZ", tb3.name);
      assertEquals(42, tb3.age);
      assertEquals("123 UK", tb3.country);
      assertEquals("123 UK", tb3.countryFactory.getObject());
      System.getProperties().put("country", "US");
      assertEquals("123 UK", tb3.country);
      assertEquals("123 US", tb3.countryFactory.getObject());
      System.getProperties().put("country", "UK");
      assertEquals("123 UK", tb3.country);
      assertEquals("123 UK", tb3.countryFactory.getObject());
      assertSame(tb0, tb3.tb);

      tb3 = (ValueTestBean) SerializationTestUtils.serializeAndDeserialize(tb3);
      assertEquals("123 UK", tb3.countryFactory.getObject());

      ConstructorValueTestBean tb4 = ac.getBean("tb4", ConstructorValueTestBean.class);
      assertEquals("XXXmyNameYYY42ZZZ", tb4.name);
      assertEquals(42, tb4.age);
      assertEquals("123 UK", tb4.country);
      assertSame(tb0, tb4.tb);

      MethodValueTestBean tb5 = ac.getBean("tb5", MethodValueTestBean.class);
      assertEquals("XXXmyNameYYY42ZZZ", tb5.name);
      assertEquals(42, tb5.age);
      assertEquals("123 UK", tb5.country);
      assertSame(tb0, tb5.tb);

      PropertyValueTestBean tb6 = ac.getBean("tb6", PropertyValueTestBean.class);
      assertEquals("XXXmyNameYYY42ZZZ", tb6.name);
      assertEquals(42, tb6.age);
      assertEquals("123 UK", tb6.country);
      assertSame(tb0, tb6.tb);
    } finally {
      System.getProperties().remove("country");
    }
  }