2010-06-03 3 views
4

내가 지우개 유형의 희생자가 될 수 있다고 생각하지만 처음에는 다른 사람들과 먼저 확인해 볼 것이라고 생각했습니다.Java Generics 호 (봄)

public interface FooFactory { 
    public <T extends Bar> Foo<T> createFoo(Class<T> clazz); 
} 

이 코드를 작성하는 완벽하게 유효합니다

나는 이런 식으로 뭔가를 할 수있는 요구 사항을 가지고있다. 그러나 스프링 BeanFactory을 사용하여이 기능을 구현하려고하는데 할 수 없습니다.

내가 뭘하려는 당신이 볼 수 있듯이

public class FooFactoryImpl implements BeanFactoryAware { 
    private BeanFactory beanFactory; 

    public <T extends Bar> Foo<T> createFoo(Class<T> clazz) { 
     return beanFactory.getBean(?????????); 
    } 

    public void setBeanFactory(BeanFactory beanFactory) { 
     this.beanFactory = beanFactory; 
    } 
} 

, 내가 넣어했습니다 ... 이것이다 ???????? 여기서 나는 타입 Foo<T>의 빈을 검색하고 싶습니다. 여기서 T는 Bar를 확장합니다. 그러나, 유형 Foo<T>의 클래스 객체를 파생시킬 수 없으므로 내가하려는 것은 불가능하다고 가정합니다.

다른 사람이 이것을 시도하거나 내가 수행하려고 시도하는 것을 구현하는 다른 방법을 본 적이 있습니까?

감사합니다,

앤드류

+0

'clazz' 매개 변수는 무엇입니까? –

+0

왜 콩 공장을 사용하려고합니까? 확실히 표준 Spring 설정을 사용하여이를 수행 할 수 있습니까? –

+0

@Rob 사람들은 bean factory를 사용하여 때때로 게으른 것을 제어하거나 여러 인스턴스를 얻기 위해 프로토 타입을 이용하는 것보다 수명을 더 세밀하게 제어합니다. – bmargulies

답변

1

, 난 당신이 실제로 Foo<T>의 서브 클래스를 추측 수퍼 클래스 정의에서 유형 매개 변수가 지워지지 않는다는 사실을 사용할 수 있습니다.

public class FooFactory implements ApplicationContextAware { 

    private Map<Class<?>, Foo<?>> beans = new HashMap<Class<?>, Foo<?>>(); 

    @SuppressWarnings("unchecked") 
    public <T> Foo<T> createFoo(Class<T> c) { 
     return (Foo<T>) beans.get(c); 
    } 

    @SuppressWarnings("unchecked") 
    public void setApplicationContext(ApplicationContext ctx) 
      throws BeansException { 

     Collection<Foo> candidates = ctx.getBeansOfType(Foo.class).values(); 
     for (Foo candidate: candidates) { 
      Type superclass = candidate.getClass().getGenericSuperclass(); 
      if (superclass instanceof ParameterizedType) { 
       ParameterizedType t = (ParameterizedType) superclass; 
       Class<?> p = (Class<?>) t.getActualTypeArguments()[0]; 
       beans.put(p, candidate); 
      } 
     } 
    } 
} 
+0

나는이 라인을 따라 뭔가를 연구했다. 의견을 보내 주셔서 감사합니다. – DrewEaster

3

예,이 유형의 삭제 상황이다. Foo<T>Class을 가져올 수 없으므로 Foo으로 작업하고 경고를 표시하지 않아야합니다.

@SuppressWarnings("unchecked") 
public <T extends Bar> Foo<T> createFoo(Class<T> clazz) { 
     return (Foo<T>) beanFactory.getBean("Name of Bean", Foo.class); 
} 

당신은 this file 흥미를 찾을 수 있습니다 - 그것은 아파치 CXF이 모든 불행한 사건을 중앙 집중화하는 데 사용 억제 경고와 함께 유틸리티 클래스입니다.

물론이 모든 것은 XML (또는 무엇이든) 구성이 사용할 수있는 Foo이 될 것이라고 가정합니다. -이 경우

<bean id = "fooInteger" class = "FooInteger" /> 
<bean id = "fooString" class = "FooString" /> 

abstract public class Foo<T> { ... } 

public class FooString extends Foo<String> { ... } 
public class FooInteger extends Foo<String> { ... } 

: 당신이 Spring 컨텍스트에서 전문 T와 유형 Foo<T>의 콩을 정의 할 수 없기 때문에

+0

+1 할 기회가 있기 전에 대답하기 위해 +1, 매개 변수 clazz는 필요하지 않습니다. –

+0

@And 확실합니까? 매개 변수 목록에 등의 객체가 없기 때문에 javac에 특정 호출에 필요한 T가 무엇인지 알려줄 필요가 있다고 생각했습니다. 나는 주제가 삐걱 거리다는 것을 인정한다. 혼란 스러울 때 대답을 편집해라. – bmargulies

+0

'Foo var = fooFactoryImpl.createFoo()'와 같이하면 컴파일러는 변수 (이 경우 Bar)에서 시간을 유추합니다. 그리고 특정 유형을 사용하고자한다면 항상 fooFactoryImpl. createFoo();를 호출 할 수 있습니다. –