2017-08-17 20 views
0

ジェネリックBeanの構築の自動化の仕組みを提供するSpringのメカニズムはありますか?SpringジェネリックBeanファクトリ

よう
class Foo<T> { 
    private final T type; 
    ... 
} 

と依存関係:

@Autowired 
private Foo<String> foo; 

私は、何らかの形で、提供して春にいくつかのメカニズムを使用したいのですが、私のようなクラス定義を持っている場合などについては、

Tを依存関係の定義(上記の例ではString)から削除し、自動インスタンス作成の方法を提供しますか?あなたの春の設定でこれを定義することで

答えて

1

:あなたは春のブートを使用する場合は、あなたが@ConditionalOnProperty@ConditionalOnBeanを追加することができます

@Bean 
public Foo<String> foo() { 
    return new Foo<>(String.class); 
} 

@Bean 
public Foo<String> foo() { 
    return new Foo<>("bar"); 
} 

または値の代わりに、あなたは型を指定することができますBeanのインスタンス化をダイナミックにします。

(更新)宣言を避ける場合は、DefaultListableBeanFactoryApplicationContextを拡張する必要があります。ここでは春ブーツとの実施例である:

@Controller 
@EnableAutoConfiguration 
public class BeanFactoryTest { 
    public static void main(String[] args) throws Exception { 
     SpringApplication app = new SpringApplication(BeanFactoryTest.class); 
     app.setApplicationContextClass(CustomAppContext.class); 
     app.run(args); 
    } 

    @Autowired 
    private Foo<String> foo1; 

    @Autowired 
    private Foo<String> foo2; 

    @Autowired 
    private Foo<Integer> foo3; 

    @PostConstruct 
    public void initialize() { 
     System.out.println(foo1); // prints [email protected] 
     System.out.println(foo2); // prints [email protected] 
     System.out.println(foo3); // prints [email protected] 
    } 

    public static class CustomAppContext extends AnnotationConfigApplicationContext { 
     public CustomAppContext() { 
      super(new CustomBeanFactory()); 
     } 
    } 

    public static class CustomBeanFactory extends DefaultListableBeanFactory { 
     @Override 
     protected Map<String, Object> findAutowireCandidates(String beanName, Class<?> requiredType, DependencyDescriptor descriptor) { 
      Map<String, Object> map = super.findAutowireCandidates(beanName, requiredType, descriptor); 

      if (Foo.class.isAssignableFrom(requiredType)) { 
       ResolvableType type = ResolvableType.forField(descriptor.getField()); 
       ResolvableType genericType = type.getGeneric(0); 
       Class<?> genericTypeRaw = genericType.getRawClass(); 

       boolean hasInstance = 
         map.values() 
          .parallelStream() 
          .map(Foo.class::cast) 
          .map(Foo::getType) 
          .filter(genericTypeRaw::isAssignableFrom) 
          .findFirst() 
          .isPresent(); 

       if (!hasInstance) { 
        super.registerResolvableDependency(requiredType, new Foo<>(genericTypeRaw)); 

        map = super.findAutowireCandidates(beanName, requiredType, descriptor); 
       } 
      } 

      return map; 
     } 
    } 

    public static class Foo<T> { 
     private final Class<T> type; 

     public Foo(Class<T> type) { 
      this.type = type; 
     } 

     public Class<T> getType() { 
      return type; 
     } 
    } 
} 
+0

私は実装を追加しました。作業は最適化することができます。 –

関連する問題