Spring-自动装配通用接口的通用实现 [英] Spring - autowiring generic implementation of generic interface

查看:436
本文介绍了Spring-自动装配通用接口的通用实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've got small question. It's probably trivial, but I've never faced it before.

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

I have generic interface and a generic implementation of it. I wanted to autowire it, but an error occured. Here are the details:

接口

Interface

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

    T deserialize(String toBeDeserialized, Class<T> resultType);
}

实施

Implementation

@Service
public class JsonSerializer<T extends Serializable> implements Serializing<T> {
   /** code **/
}

自动接线尝试

Autowire attempt

private NoteDAO noteDAO;

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

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

错误

Error

Parameter 1 of constructor in somepackagepath.NoteController required a bean of type 'anotherpackagepath.Serializing' that could not be found.

我想使其尽可能简单.我已经检查过Web,但是只发现了有关在配置中定义确切的bean的信息.我更愿意避免这种情况.

I want to keep it as simple as possible. I've check the web, but I've found only about defining my exact beans in configuration. I prefer to avoid it if possible.

推荐答案

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

In your specific case, Spring doesn't allow to use a generic type to be wired as dependency such as :

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

出于一个非常简单的原因:一致性.
您使用@Service制成的Spring bean的这种依赖关系:

for a very simple reason : consistency.
This dependency that you made a Spring bean with @Service :

@Service
public class JsonSerializer<T extends Serializable> implements Serializing<T> {
   /** code **/
}

可以连接到其他bean中.

can be wired into other beans.

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

Imagine that the beans that depend on the Serializing instance don't use the same generic : Serializing<UserComment> in Foo and Serializing<UserQuestion> in Bar such as :

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;
    }

}

这里Serializing对象是相同的,但是每个bean在on上声明了不同的泛型.
这样会破坏泛型的类型安全性.

Here the Serializing object is the same but each bean declares a distinct generic on.
So it would break the type safety of the generic type.

事实上,由于 Spring(来自Spring 4)拥有一个能够解析类型的解析器:

在幕后,新的ResolvableType类提供了以下逻辑: 实际使用泛型类型.您可以自己轻松地使用它 浏览并解析类型信息. ResolvableType上的大多数方法 自己将返回ResolvableType

behind the scenes, the new ResolvableType class provides the logic of actually working with generic types. You can use it yourself to easily navigate and resolve type information. Most methods on ResolvableType will themselves return a ResolvableType

在Spring 4之前,您还具有其他变通方法来接受bean依赖项中的泛型类型.
真正的问题是,您必须用@Service注释一个泛型类以使其成为bean,而该类是必须配置为bean的该泛型类的实例.

And before Spring 4 you also had other workaround to accept generic types in the bean dependencies.
The real problem is that you annotated a generic class with @Service to make it a bean while it is an instance of this generic class that has to be configured as a bean.

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

So to achieve what you want to do, declare the JsonSerializer beans that you want to instantiate in a @Configuration class :

@Configuration
public class SerializingBeans {

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

    @Bean
    public JsonSerializer<UserAnswer> userAnswerSerializer() {
        return new JsonSerializer<UserAnswer>();
    }
}

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

You can now wire the dependency as a generic type :

@Service
public class NoteController {

    private Serializing<UserComment> userCommentSerializer;

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

    }
}

这篇关于Spring-自动装配通用接口的通用实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆