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?

4

2 回答 2

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

于 2013-05-27T20:13:30.830 回答
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>() {}
于 2013-06-07T21:51:04.890 回答