Package org.springframework.context.annotation

Source Code of org.springframework.context.annotation.ConfigurationClassPostProcessorTests$Foo

/*
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.context.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.annotation.PostConstruct;

import org.junit.Before;
import org.junit.Test;

import org.springframework.aop.scope.ScopedObject;
import org.springframework.aop.scope.ScopedProxyUtils;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.ChildBeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.componentscan.simple.SimpleComponent;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.DescriptiveResource;
import org.springframework.stereotype.Component;
import org.springframework.tests.sample.beans.ITestBean;
import org.springframework.tests.sample.beans.TestBean;
import org.springframework.util.Assert;

import static org.junit.Assert.*;

/**
* @author Chris Beams
* @author Juergen Hoeller
* @author Sam Brannen
*/
public class ConfigurationClassPostProcessorTests {

  private DefaultListableBeanFactory beanFactory;


  @Before
  public void setUp() {
    DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
    QualifierAnnotationAutowireCandidateResolver acr = new QualifierAnnotationAutowireCandidateResolver();
    acr.setBeanFactory(bf);
    bf.setAutowireCandidateResolver(acr);
    this.beanFactory = bf;
  }

  /**
   * Enhanced {@link Configuration} classes are only necessary for respecting
   * certain bean semantics, like singleton-scoping, scoped proxies, etc.
   * <p>Technically, {@link ConfigurationClassPostProcessor} could fail to enhance the
   * registered Configuration classes and many use cases would still work.
   * Certain cases, however, like inter-bean singleton references would not.
   * We test for such a case below, and in doing so prove that enhancement is
   * working.
   */
  @Test
  public void enhancementIsPresentBecauseSingletonSemanticsAreRespected() {
    beanFactory.registerBeanDefinition("config", new RootBeanDefinition(SingletonBeanConfig.class));
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.postProcessBeanFactory(beanFactory);
    Foo foo = beanFactory.getBean("foo", Foo.class);
    Bar bar = beanFactory.getBean("bar", Bar.class);
    assertSame(foo, bar.foo);
  }

  @Test
  public void configurationIntrospectionOfInnerClassesWorksWithDotNameSyntax() {
    beanFactory.registerBeanDefinition("config", new RootBeanDefinition(getClass().getName() + ".SingletonBeanConfig"));
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.postProcessBeanFactory(beanFactory);
    Foo foo = beanFactory.getBean("foo", Foo.class);
    Bar bar = beanFactory.getBean("bar", Bar.class);
    assertSame(foo, bar.foo);
  }

  /**
   * Tests the fix for SPR-5655, a special workaround that prefers reflection
   * over ASM if a bean class is already loaded.
   */
  @Test
  public void alreadyLoadedConfigurationClasses() {
    beanFactory.registerBeanDefinition("unloadedConfig", new RootBeanDefinition(UnloadedConfig.class.getName()));
    beanFactory.registerBeanDefinition("loadedConfig", new RootBeanDefinition(LoadedConfig.class));
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.postProcessBeanFactory(beanFactory);
    beanFactory.getBean("foo");
    beanFactory.getBean("bar");
  }

  /**
   * Tests whether a bean definition without a specified bean class is handled
   * correctly.
   */
  @Test
  public void postProcessorIntrospectsInheritedDefinitionsCorrectly() {
    beanFactory.registerBeanDefinition("config", new RootBeanDefinition(SingletonBeanConfig.class));
    beanFactory.registerBeanDefinition("parent", new RootBeanDefinition(TestBean.class));
    beanFactory.registerBeanDefinition("child", new ChildBeanDefinition("parent"));
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.postProcessBeanFactory(beanFactory);
    Foo foo = beanFactory.getBean("foo", Foo.class);
    Bar bar = beanFactory.getBean("bar", Bar.class);
    assertSame(foo, bar.foo);
  }

  @Test
  public void postProcessorWorksWithComposedConfigurationUsingReflection() {
    RootBeanDefinition beanDefinition = new RootBeanDefinition(ComposedConfigurationClass.class);
    assertSupportForComposedAnnotation(beanDefinition);
  }

  @Test
  public void postProcessorWorksWithComposedConfigurationUsingAsm() {
    RootBeanDefinition beanDefinition = new RootBeanDefinition(ComposedConfigurationClass.class.getName());
    assertSupportForComposedAnnotation(beanDefinition);
  }

  @Test
  public void postProcessorWorksWithComposedConfigurationWithAttributeOverrideForBasePackageUsingReflection() {
    RootBeanDefinition beanDefinition = new RootBeanDefinition(
        ComposedConfigurationWithAttributeOverrideForBasePackage.class);
    assertSupportForComposedAnnotation(beanDefinition);
  }

  @Test
  public void postProcessorWorksWithComposedConfigurationWithAttributeOverrideForBasePackageUsingAsm() {
    RootBeanDefinition beanDefinition = new RootBeanDefinition(
        ComposedConfigurationWithAttributeOverrideForBasePackage.class.getName());
    assertSupportForComposedAnnotation(beanDefinition);
  }

  @Test
  public void postProcessorWorksWithComposedConfigurationWithAttributeOverrideForExcludeFilterUsingReflection() {
    RootBeanDefinition beanDefinition = new RootBeanDefinition(
        ComposedConfigurationWithAttributeOverrideForExcludeFilter.class);
    assertSupportForComposedAnnotationWithExclude(beanDefinition);
  }

  @Test
  public void postProcessorWorksWithComposedConfigurationWithAttributeOverrideForExcludeFilterUsingAsm() {
    RootBeanDefinition beanDefinition = new RootBeanDefinition(
        ComposedConfigurationWithAttributeOverrideForExcludeFilter.class.getName());
    assertSupportForComposedAnnotationWithExclude(beanDefinition);
  }

  @Test
  public void postProcessorWorksWithComposedComposedConfigurationWithAttributeOverridesUsingReflection() {
    RootBeanDefinition beanDefinition = new RootBeanDefinition(
        ComposedComposedConfigurationWithAttributeOverridesClass.class);
    assertSupportForComposedAnnotation(beanDefinition);
  }

  @Test
  public void postProcessorWorksWithComposedComposedConfigurationWithAttributeOverridesUsingAsm() {
    RootBeanDefinition beanDefinition = new RootBeanDefinition(
        ComposedComposedConfigurationWithAttributeOverridesClass.class.getName());
    assertSupportForComposedAnnotation(beanDefinition);
  }

  @Test
  public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesUsingReflection() {
    RootBeanDefinition beanDefinition = new RootBeanDefinition(
        MetaComponentScanConfigurationWithAttributeOverridesClass.class);
    assertSupportForComposedAnnotation(beanDefinition);
  }

  @Test
  public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesUsingAsm() {
    RootBeanDefinition beanDefinition = new RootBeanDefinition(
        MetaComponentScanConfigurationWithAttributeOverridesClass.class.getName());
    assertSupportForComposedAnnotation(beanDefinition);
  }

  @Test
  public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesSubclassUsingReflection() {
    RootBeanDefinition beanDefinition = new RootBeanDefinition(
        SubMetaComponentScanConfigurationWithAttributeOverridesClass.class);
    assertSupportForComposedAnnotation(beanDefinition);
  }

  @Test
  public void postProcessorWorksWithMetaComponentScanConfigurationWithAttributeOverridesSubclassUsingAsm() {
    RootBeanDefinition beanDefinition = new RootBeanDefinition(
        SubMetaComponentScanConfigurationWithAttributeOverridesClass.class.getName());
    assertSupportForComposedAnnotation(beanDefinition);
  }

  private void assertSupportForComposedAnnotation(RootBeanDefinition beanDefinition) {
    beanFactory.registerBeanDefinition("config", beanDefinition);
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.setEnvironment(new StandardEnvironment());
    pp.postProcessBeanFactory(beanFactory);
    SimpleComponent simpleComponent = beanFactory.getBean(SimpleComponent.class);
    assertNotNull(simpleComponent);
  }

  private void assertSupportForComposedAnnotationWithExclude(RootBeanDefinition beanDefinition) {
    beanFactory.registerBeanDefinition("config", beanDefinition);
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.setEnvironment(new StandardEnvironment());
    pp.postProcessBeanFactory(beanFactory);
    try {
      beanFactory.getBean(SimpleComponent.class);
      fail("Should have thrown NoSuchBeanDefinitionException");
    }
    catch (NoSuchBeanDefinitionException ex) {
      // expected
    }
  }

  @Test
  public void postProcessorOverridesNonApplicationBeanDefinitions() {
    RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
    rbd.setRole(RootBeanDefinition.ROLE_SUPPORT);
    beanFactory.registerBeanDefinition("bar", rbd);
    beanFactory.registerBeanDefinition("config", new RootBeanDefinition(SingletonBeanConfig.class));
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.postProcessBeanFactory(beanFactory);
    Foo foo = beanFactory.getBean("foo", Foo.class);
    Bar bar = beanFactory.getBean("bar", Bar.class);
    assertSame(foo, bar.foo);
  }

  @Test
  public void postProcessorDoesNotOverrideRegularBeanDefinitions() {
    RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
    rbd.setResource(new DescriptiveResource("XML or something"));
    beanFactory.registerBeanDefinition("bar", rbd);
    beanFactory.registerBeanDefinition("config", new RootBeanDefinition(SingletonBeanConfig.class));
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.postProcessBeanFactory(beanFactory);
    beanFactory.getBean("foo", Foo.class);
    beanFactory.getBean("bar", TestBean.class);
  }

  @Test
  public void postProcessorDoesNotOverrideRegularBeanDefinitionsEvenWithScopedProxy() {
    RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class);
    rbd.setResource(new DescriptiveResource("XML or something"));
    BeanDefinitionHolder proxied = ScopedProxyUtils.createScopedProxy(
        new BeanDefinitionHolder(rbd, "bar"), beanFactory, true);
    beanFactory.registerBeanDefinition("bar", proxied.getBeanDefinition());
    beanFactory.registerBeanDefinition("config", new RootBeanDefinition(SingletonBeanConfig.class));
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.postProcessBeanFactory(beanFactory);
    beanFactory.getBean("foo", Foo.class);
    beanFactory.getBean("bar", TestBean.class);
  }

  @Test
  public void scopedProxyTargetMarkedAsNonAutowireCandidate() {
    AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
    bpp.setBeanFactory(beanFactory);
    beanFactory.addBeanPostProcessor(bpp);
    beanFactory.registerBeanDefinition("config", new RootBeanDefinition(ScopedProxyConfigurationClass.class));
    beanFactory.registerBeanDefinition("consumer", new RootBeanDefinition(ScopedProxyConsumer.class));
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.postProcessBeanFactory(beanFactory);
    ITestBean injected = beanFactory.getBean("consumer", ScopedProxyConsumer.class).testBean;
    assertTrue(injected instanceof ScopedObject);
    assertSame(beanFactory.getBean("scopedClass"), injected);
    assertSame(beanFactory.getBean(ITestBean.class), injected);
  }

  @Test
  public void processingAllowedOnlyOncePerProcessorRegistryPair() {
    DefaultListableBeanFactory bf1 = new DefaultListableBeanFactory();
    DefaultListableBeanFactory bf2 = new DefaultListableBeanFactory();
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.postProcessBeanFactory(bf1); // first invocation -- should succeed
    try {
      pp.postProcessBeanFactory(bf1); // second invocation for bf1 -- should throw
      fail("expected exception");
    }
    catch (IllegalStateException ex) {
    }
    pp.postProcessBeanFactory(bf2); // first invocation for bf2 -- should succeed
    try {
      pp.postProcessBeanFactory(bf2); // second invocation for bf2 -- should throw
      fail("expected exception");
    }
    catch (IllegalStateException ex) {
    }
  }

  @Test
  public void genericsBasedInjection() {
    AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
    bpp.setBeanFactory(beanFactory);
    beanFactory.addBeanPostProcessor(bpp);
    RootBeanDefinition bd = new RootBeanDefinition(RepositoryInjectionBean.class);
    bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
    beanFactory.registerBeanDefinition("annotatedBean", bd);
    beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RepositoryConfiguration.class));
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.postProcessBeanFactory(beanFactory);

    RepositoryInjectionBean bean = (RepositoryInjectionBean) beanFactory.getBean("annotatedBean");
    assertEquals("Repository<String>", bean.stringRepository.toString());
    assertEquals("Repository<Integer>", bean.integerRepository.toString());
  }

  @Test
  public void genericsBasedInjectionWithScoped() {
    AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
    bpp.setBeanFactory(beanFactory);
    beanFactory.addBeanPostProcessor(bpp);
    RootBeanDefinition bd = new RootBeanDefinition(RepositoryInjectionBean.class);
    bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
    beanFactory.registerBeanDefinition("annotatedBean", bd);
    beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(ScopedRepositoryConfiguration.class));
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.postProcessBeanFactory(beanFactory);

    RepositoryInjectionBean bean = (RepositoryInjectionBean) beanFactory.getBean("annotatedBean");
    assertEquals("Repository<String>", bean.stringRepository.toString());
    assertEquals("Repository<Integer>", bean.integerRepository.toString());
  }

  @Test
  public void genericsBasedInjectionWithScopedProxy() {
    AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
    bpp.setBeanFactory(beanFactory);
    beanFactory.addBeanPostProcessor(bpp);
    RootBeanDefinition bd = new RootBeanDefinition(RepositoryInjectionBean.class);
    bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
    beanFactory.registerBeanDefinition("annotatedBean", bd);
    beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(ScopedProxyRepositoryConfiguration.class));
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.postProcessBeanFactory(beanFactory);
    beanFactory.freezeConfiguration();

    RepositoryInjectionBean bean = (RepositoryInjectionBean) beanFactory.getBean("annotatedBean");
    assertEquals("Repository<String>", bean.stringRepository.toString());
    assertEquals("Repository<Integer>", bean.integerRepository.toString());
  }

  @Test
  public void genericsBasedInjectionWithImplTypeAtInjectionPoint() {
    AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
    bpp.setBeanFactory(beanFactory);
    beanFactory.addBeanPostProcessor(bpp);
    RootBeanDefinition bd = new RootBeanDefinition(SpecificRepositoryInjectionBean.class);
    bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
    beanFactory.registerBeanDefinition("annotatedBean", bd);
    beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(SpecificRepositoryConfiguration.class));
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.postProcessBeanFactory(beanFactory);
    beanFactory.preInstantiateSingletons();

    SpecificRepositoryInjectionBean bean = (SpecificRepositoryInjectionBean) beanFactory.getBean("annotatedBean");
    assertSame(beanFactory.getBean("genericRepo"), bean.genericRepository);
  }

  @Test
  public void genericsBasedInjectionWithFactoryBean() {
    AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
    bpp.setBeanFactory(beanFactory);
    beanFactory.addBeanPostProcessor(bpp);
    RootBeanDefinition bd = new RootBeanDefinition(RepositoryFactoryBeanInjectionBean.class);
    bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
    beanFactory.registerBeanDefinition("annotatedBean", bd);
    beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RepositoryFactoryBeanConfiguration.class));
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.postProcessBeanFactory(beanFactory);
    beanFactory.preInstantiateSingletons();

    RepositoryFactoryBeanInjectionBean bean = (RepositoryFactoryBeanInjectionBean) beanFactory.getBean("annotatedBean");
    assertSame(beanFactory.getBean("&repoFactoryBean"), bean.repositoryFactoryBean);
    assertSame(beanFactory.getBean("&repoFactoryBean"), bean.qualifiedRepositoryFactoryBean);
    assertSame(beanFactory.getBean("&repoFactoryBean"), bean.prefixQualifiedRepositoryFactoryBean);
  }

  @Test
  public void genericsBasedInjectionWithRawMatch() {
    beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(RawMatchingConfiguration.class));
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.postProcessBeanFactory(beanFactory);

    assertSame(beanFactory.getBean("rawRepo"), beanFactory.getBean("repoConsumer"));
  }

  @Test
  public void genericsBasedInjectionWithWildcardMatch() {
    beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(WildcardMatchingConfiguration.class));
    ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
    pp.postProcessBeanFactory(beanFactory);

    assertSame(beanFactory.getBean("genericRepo"), beanFactory.getBean("repoConsumer"));
  }

  @Test
  public void genericsBasedInjectionWithWildcardWithExtendsMatch() {
    beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(WildcardWithExtendsConfiguration.class));
    new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);

    assertSame(beanFactory.getBean("stringRepo"), beanFactory.getBean("repoConsumer"));
  }

  @Test
  public void genericsBasedInjectionWithWildcardWithGenericExtendsMatch() {
    beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(WildcardWithGenericExtendsConfiguration.class));
    new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);

    assertSame(beanFactory.getBean("genericRepo"), beanFactory.getBean("repoConsumer"));
  }

  @Test
  public void testSelfReferenceExclusionForFactoryMethodOnSameBean() {
    AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
    bpp.setBeanFactory(beanFactory);
    beanFactory.addBeanPostProcessor(bpp);
    beanFactory.addBeanPostProcessor(new CommonAnnotationBeanPostProcessor());
    beanFactory.registerBeanDefinition("configClass", new RootBeanDefinition(ConcreteConfig.class));
    beanFactory.registerBeanDefinition("serviceBeanProvider", new RootBeanDefinition(ServiceBeanProvider.class));
    new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
    beanFactory.preInstantiateSingletons();
  }

  @Test
  public void testCircularDependency() {
    AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
    bpp.setBeanFactory(beanFactory);
    beanFactory.addBeanPostProcessor(bpp);
    beanFactory.registerBeanDefinition("configClass1", new RootBeanDefinition(A.class));
    beanFactory.registerBeanDefinition("configClass2", new RootBeanDefinition(AStrich.class));
    new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
    try {
      beanFactory.preInstantiateSingletons();
      fail("Should have thrown BeanCreationException");
    }
    catch (BeanCreationException ex) {
      assertTrue(ex.getMessage().contains("Circular reference"));
    }
  }

  @Test
  public void testCircularDependencyWithApplicationContext() {
    try {
      new AnnotationConfigApplicationContext(A.class, AStrich.class);
      fail("Should have thrown BeanCreationException");
    }
    catch (BeanCreationException ex) {
      assertTrue(ex.getMessage().contains("Circular reference"));
    }
  }


  // -------------------------------------------------------------------------

  @Configuration
  static class SingletonBeanConfig {

    public @Bean
    Foo foo() {
      return new Foo();
    }

    public @Bean
    Bar bar() {
      return new Bar(foo());
    }
  }

  static class Foo {
  }

  static class Bar {

    final Foo foo;

    public Bar(Foo foo) {
      this.foo = foo;
    }
  }

  @Configuration
  static class UnloadedConfig {

    public @Bean
    Foo foo() {
      return new Foo();
    }
  }

  @Configuration
  static class LoadedConfig {

    public @Bean
    Bar bar() {
      return new Bar(new Foo());
    }
  }

  public static class ScopedProxyConsumer {

    @Autowired
    public ITestBean testBean;
  }

  @Configuration
  public static class ScopedProxyConfigurationClass {

    @Bean
    @Lazy
    @Scope(proxyMode = ScopedProxyMode.INTERFACES)
    public ITestBean scopedClass() {
      return new TestBean();
    }
  }

  public static class Repository<T> {
  }

  public static class GenericRepository<T> extends Repository<T> {
  }

  public static class RepositoryFactoryBean<T> implements FactoryBean<T> {

    @Override
    public T getObject() {
      throw new IllegalStateException();
    }

    @Override
    public Class<?> getObjectType() {
      return Object.class;
    }

    @Override
    public boolean isSingleton() {
      return false;
    }
  }

  public static class RepositoryInjectionBean {

    @Autowired
    public Repository<String> stringRepository;

    @Autowired
    public Repository<Integer> integerRepository;
  }

  @Configuration
  public static class RepositoryConfiguration {

    @Bean
    public Repository<String> stringRepo() {
      return new Repository<String>() {
        @Override
        public String toString() {
          return "Repository<String>";
        }
      };
    }

    @Bean
    public Repository<Integer> integerRepo() {
      return new Repository<Integer>() {
        @Override
        public String toString() {
          return "Repository<Integer>";
        }
      };
    }

    @Bean
    public Repository<?> genericRepo() {
      return new Repository<Object>() {
        @Override
        public String toString() {
          return "Repository<Object>";
        }
      };
    }
  }

  @Configuration
  public static class ScopedRepositoryConfiguration {

    @Bean
    @Scope("prototype")
    public Repository<String> stringRepo() {
      return new Repository<String>() {
        @Override
        public String toString() {
          return "Repository<String>";
        }
      };
    }

    @Bean
    @Scope("prototype")
    public Repository<Integer> integerRepo() {
      return new Repository<Integer>() {
        @Override
        public String toString() {
          return "Repository<Integer>";
        }
      };
    }

    @Bean
    @Scope("prototype")
    @SuppressWarnings("rawtypes")
    public Repository genericRepo() {
      return new Repository<Object>() {
        @Override
        public String toString() {
          return "Repository<Object>";
        }
      };
    }
  }

  @Configuration
  public static class ScopedProxyRepositoryConfiguration {

    @Bean
    @Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
    public Repository<String> stringRepo() {
      return new Repository<String>() {
        @Override
        public String toString() {
          return "Repository<String>";
        }
      };
    }

    @Bean
    @Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
    public Repository<Integer> integerRepo() {
      return new Repository<Integer>() {
        @Override
        public String toString() {
          return "Repository<Integer>";
        }
      };
    }
  }

  public static class SpecificRepositoryInjectionBean {

    @Autowired
    public GenericRepository<?> genericRepository;
  }

  @Configuration
  public static class SpecificRepositoryConfiguration {

    @Bean
    public Repository<Object> genericRepo() {
      return new GenericRepository<Object>();
    }
  }

  public static class RepositoryFactoryBeanInjectionBean {

    @Autowired
    public RepositoryFactoryBean<?> repositoryFactoryBean;

    @Autowired
    @Qualifier("repoFactoryBean")
    public RepositoryFactoryBean<?> qualifiedRepositoryFactoryBean;

    @Autowired
    @Qualifier("&repoFactoryBean")
    public RepositoryFactoryBean<?> prefixQualifiedRepositoryFactoryBean;
  }

  @Configuration
  public static class RepositoryFactoryBeanConfiguration {

    @Bean
    public RepositoryFactoryBean<Object> repoFactoryBean() {
      return new RepositoryFactoryBean<>();
    }
  }

  @Configuration
  public static class RawMatchingConfiguration {

    @Bean
    @SuppressWarnings("rawtypes")
    public Repository rawRepo() {
      return new Repository();
    }

    @Bean
    public Object repoConsumer(Repository<String> repo) {
      return repo;
    }
  }

  @Configuration
  public static class WildcardMatchingConfiguration {

    @Bean
    @SuppressWarnings("rawtypes")
    public Repository<?> genericRepo() {
      return new Repository();
    }

    @Bean
    public Object repoConsumer(Repository<String> repo) {
      return repo;
    }
  }

  @Configuration
  public static class WildcardWithExtendsConfiguration {

    @Bean
    public Repository<? extends String> stringRepo() {
      return new Repository<String>();
    }

    @Bean
    public Repository<? extends Number> numberRepo() {
      return new Repository<Number>();
    }

    @Bean
    public Object repoConsumer(Repository<? extends String> repo) {
      return repo;
    }
  }

  @Configuration
  public static class WildcardWithGenericExtendsConfiguration {

    @Bean
    public Repository<? extends Object> genericRepo() {
      return new Repository<String>();
    }

    @Bean
    public Repository<? extends Number> numberRepo() {
      return new Repository<Number>();
    }

    @Bean
    public Object repoConsumer(Repository<String> repo) {
      return repo;
    }
  }

  @Configuration
  @ComponentScan(basePackages = "org.springframework.context.annotation.componentscan.simple")
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.TYPE)
  public static @interface ComposedConfiguration {
  }

  @ComposedConfiguration
  public static class ComposedConfigurationClass {
  }

  @Configuration
  @ComponentScan
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.TYPE)
  public static @interface ComposedConfigurationWithAttributeOverrides {

    String[] basePackages() default {};

    ComponentScan.Filter[] excludeFilters() default {};
  }

  @ComposedConfigurationWithAttributeOverrides(basePackages = "org.springframework.context.annotation.componentscan.simple")
  public static class ComposedConfigurationWithAttributeOverrideForBasePackage {
  }

  @ComposedConfigurationWithAttributeOverrides(basePackages = "org.springframework.context.annotation.componentscan.simple",
      excludeFilters = @ComponentScan.Filter(Component.class))
  public static class ComposedConfigurationWithAttributeOverrideForExcludeFilter {
  }

  @ComposedConfigurationWithAttributeOverrides
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.TYPE)
  public static @interface ComposedComposedConfigurationWithAttributeOverrides {

    String[] basePackages() default {};
  }

  @ComposedComposedConfigurationWithAttributeOverrides(basePackages = "org.springframework.context.annotation.componentscan.simple")
  public static class ComposedComposedConfigurationWithAttributeOverridesClass {
  }

  @ComponentScan
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.TYPE)
  public static @interface MetaComponentScan {
  }

  @MetaComponentScan
  @Configuration
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.TYPE)
  public static @interface MetaComponentScanConfigurationWithAttributeOverrides {

    String[] basePackages() default {};
  }

  @MetaComponentScanConfigurationWithAttributeOverrides(basePackages = "org.springframework.context.annotation.componentscan.simple")
  public static class MetaComponentScanConfigurationWithAttributeOverridesClass {
  }

  @Configuration
  public static class SubMetaComponentScanConfigurationWithAttributeOverridesClass extends
      MetaComponentScanConfigurationWithAttributeOverridesClass {
  }

  public static class ServiceBean {

    private final String parameter;

    public ServiceBean(String parameter) {
      this.parameter = parameter;
    }

    public String getParameter() {
      return parameter;
    }
  }

  @Configuration
  public static abstract class AbstractConfig {

    @Bean
    public ServiceBean serviceBean() {
      return provider().getServiceBean();
    }

    @Bean
    public ServiceBeanProvider provider() {
      return new ServiceBeanProvider();
    }
  }

  @Configuration
  public static class ConcreteConfig extends AbstractConfig {

    @Autowired
    private ServiceBeanProvider provider;

    @Bean
    @Override
    public ServiceBeanProvider provider() {
      return provider;
    }

    @PostConstruct
    public void validate() {
      Assert.notNull(provider);
    }
  }

  @Primary
  public static class ServiceBeanProvider {

    public ServiceBean getServiceBean() {
      return new ServiceBean("message");
    }
  }

  @Configuration
  public static class A {

    @Autowired(required=true)
    Z z;

    @Bean
    public B b() {
      if (z == null) {
        throw new NullPointerException("z is null");
      }
      return new B(z);
    }
  }

  @Configuration
  public static class AStrich {

    @Autowired
    B b;

    @Bean
    public Z z() {
      return new Z();
    }
  }

  public static class B {

    public B(Z z) {
    }
  }

  public static class Z {
  }

}
TOP

Related Classes of org.springframework.context.annotation.ConfigurationClassPostProcessorTests$Foo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.