Spring-自动装配通用接口的通用实现 [英] Spring - autowiring generic implementation of generic interface
问题描述
我有一个小问题.这可能是微不足道的,但我以前从未遇到过.
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屋!