Spring-自动装配通用接口的通用实现

Pet*_*eef 2 java generics spring autowired

我有一个小问题。这可能是微不足道的,但我以前从未遇到过。

我有通用接口及其通用实现。我想为其自动接线,但是发生了错误。详细信息如下:

接口

@Service
public interface Serializing<T extends Serializable> {
    String serialize(T toBeSerialized);

    T deserialize(String toBeDeserialized, Class<T> resultType);
}
Run Code Online (Sandbox Code Playgroud)

实作

@Service
public class JsonSerializer<T extends Serializable> implements Serializing<T> {
   /** code **/
}
Run Code Online (Sandbox Code Playgroud)

自动接线尝试

private NoteDAO noteDAO;

@Qualifier("jsonSerializer")
private Serializing<UserComment> serializer;

@Autowired
public NoteController(NoteDAO noteDAO, Serializing<UserComment> serializer) {
    this.noteDAO = noteDAO;
    this.serializer = serializer;
}
Run Code Online (Sandbox Code Playgroud)

错误

Parameter 1 of constructor in somepackagepath.NoteController required a bean of type 'anotherpackagepath.Serializing' that could not be found.
Run Code Online (Sandbox Code Playgroud)

我想让它尽可能简单。我已经检查过Web,但是只发现了有关在配置中定义确切的bean的信息。如果可能,我宁愿避免这样做。

dav*_*xxx 6

您的特定情况下,Spring不允许使用泛型类型作为依赖项进行连接,例如:

@Autowired
public NoteController(NoteDAO noteDAO, Serializing<UserComment> serializer) {
    this.noteDAO = noteDAO;
    this.serializer = serializer;
}
Run Code Online (Sandbox Code Playgroud)

原因很简单:一致性。
您通过以下方式制作了Spring bean的此依赖项@Service

@Service
public class JsonSerializer<T extends Serializable> implements Serializing<T> {
   /** code **/
}
Run Code Online (Sandbox Code Playgroud)

可以连接到其他bean。

想象一下,依赖于Serializing实例的bean 不使用相同的泛型 Serializing<UserComment>in FooSerializing<UserQuestion>in,Bar例如:

public class Foo{

    @Autowired
    public Foo(NoteDAO noteDAO, Serializing<UserComment> serializer) {
        this.noteDAO = noteDAO;
        this.serializer = serializer;
    }

}
public class Bar{

    @Autowired
    public Bar(NoteDAO noteDAO, Serializing<UserQuestion> serializer) {
        this.noteDAO = noteDAO;
        this.serializer = serializer;
    }

}
Run Code Online (Sandbox Code Playgroud)

这里的Serializing对象是相同的,但是每个bean都声明一个不同的泛型。
因此,它将破坏泛型类型的类型安全性。


实际上,删除泛型并不是真正的问题,因为Spring(来自Spring 4)拥有一个能够解析类型的Resolver

在幕后,新的ResolvableType类提供了实际使用泛型类型的逻辑。您可以自己使用它来轻松浏览和解析类型信息。ResolvableType上的大多数方法本身都会返回ResolvableType

在Spring 4之前,您还具有其他解决方法来接受Bean依赖项中的泛型类型。
真正的问题是,当必须将通用类配置@Service为Bean时,使用通用类对其进行了注释 。

因此,要实现您要执行的操作,JsonSerializer请在@Configuration类中声明要实例化的bean :

@Configuration
public class SerializingBeans {

    @Bean
    public JsonSerializer<UserComment> userCommentSerializer() {
        return new JsonSerializer<UserComment>();
    }

    @Bean
    public JsonSerializer<UserAnswer> userAnswerSerializer() {
        return new JsonSerializer<UserAnswer>();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以将依赖项作为通用类型进行连接:

@Service
public class NoteController {

    private Serializing<UserComment> userCommentSerializer;

    @Autowired
    public NoteController(Serializing<UserComment> serializer) {
        this.userCommentSerializer = serializer;

    }
}
Run Code Online (Sandbox Code Playgroud)