2

I'd like to be able to inject Guava TypeToken objects by specifying them as a bean in a Spring xml configuration. Is there a good way to do this? Has anyone written any cade/library to make this easier?

TypeToken seems to work by using reflection to introspect its generic types and is thus constructed using an anonymous class like:

new TypeToken<List<String>>() {}

Spring's xml config syntax doesn't seem to accept generics at all, presumably because it's built at runtime and doesn't "need" them (since generics are compile time checks and technically erased at runtime).

So the only way I know to instantiate a TypeToken bean is to do it in java:

TokenConfig.java:

@Configuration
public class TokenConfig {
  @Bean
  public TypeToken<List<String>> listOfStringsToken() {
      return new TypeToken<List<String>>() {};
  }
}

system-test-config.xml:

<beans>
  <context:annotation-config/>
  <bean class="com.acme.TokenConfig"/>
  <bean class="com.acme.Consumer">
    <property name="typeToken" ref="listOfStringsToken"/>
  </bean>
</beans>

Is there a way to do this with just an xml config?

KarlKFI
  • 3,102
  • 1
  • 15
  • 15
  • 1
    Since you are using Spring annotation, why configure the bean in XML again? – 卢声远 Shengyuan Lu Mar 22 '13 at 02:45
  • 1
    There are a few reasons to use xml configuration over annotation, but the main one is to separate the configuration from the implementation. This is especially useful if you have multiple users of the same implementation with different configurations. The other reason is because my employeer requires it, due to previous decisions by the architects that I can't immediately change. – KarlKFI Mar 28 '13 at 00:34

2 Answers2

0

Maybe you can use spring FactoryBeans: look for factory methods at http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html

futuretelematics
  • 1,453
  • 11
  • 23
0

To answer my own question: It IS possible to create a non-generic TypeToken using the static constructor TypeToken.of(Class), but this wont work for deeper generic types.

Here's the Spring xml config:

<bean class="com.google.common.reflect.TypeToken" factory-method="of">
  <constructor-arg type="java.lang.Class" value="java.lang.Integer" />
</bean>

Which is equivelent to:

TypeToken.of(Integer.class)

and

new TypeToken<Integer>() {}

I also found a way to use the TypeToken.of(Type) constructor with a ParameterizedType constructed using Google Guice's Types utility. Guava has one too, but it's not public. :'( I'm not sure if this is quite as robust as using TypeToken/TypeCapture, but it seems to work. Unfortunately it's pretty ugly and long... (maybe someone can simplify it?)

<bean class="com.google.common.reflect.TypeToken" factory-method="of">
  <constructor-arg index="0">
    <bean class="com.google.inject.util.Types" factory-method="newParameterizedType">
      <constructor-arg index="0">
        <value type="java.lang.Class">java.util.List</value>
      </constructor-arg>
      <constructor-arg index="1">
        <array><value type="java.lang.Class">java.lang.String</value></array>
      </constructor-arg>
    </bean>
  </constructor-arg>
</bean>

Which is equivelent to:

new TypeToken<List<String>() {}
KarlKFI
  • 3,102
  • 1
  • 15
  • 15