为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

紫衣仙女 2021-04-03 14:15:37
我有一个小问题。它可能微不足道,但我以前从未遇到过。我有通用接口及其通用实现。我想为其自动接线,但是发生了错误。详细信息如下:界面@Servicepublic interface Serializing<T extends Serializable> {    String serialize(T toBeSerialized);    T deserialize(String toBeDeserialized, Class<T> resultType);}执行@Servicepublic class JsonSerializer<T extends Serializable> implements Serializing<T> {   /** code **/}自动接线尝试private NoteDAO noteDAO;@Qualifier("jsonSerializer")private Serializing<UserComment> serializer;@Autowiredpublic NoteController(NoteDAO noteDAO, Serializing<UserComment> serializer) {    this.noteDAO = noteDAO;    this.serializer = serializer;}错误Parameter 1 of constructor in somepackagepath.NoteController required a bean of type 'anotherpackagepath.Serializing' that could not be found.我想让它尽可能简单。我已经检查过Web,但是只发现了有关在配置中定义确切的bean的信息。如果可能的话,我宁愿避免使用它。
查看完整描述

3 回答

?
慕雪6442864

TA贡献1812条经验 获得超5个赞

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


@Autowired

public NoteController(NoteDAO noteDAO, Serializing<UserComment> serializer) {

    this.noteDAO = noteDAO;

    this.serializer = serializer;

}

原因很简单:一致性。

您通过以下方式制作了Spring bean的此依赖项@Service:


@Service

public class JsonSerializer<T extends Serializable> implements Serializing<T> {

   /** code **/

}

可以连接到其他bean。


想象一下,依赖于Serializing实例的bean不使用相同的泛型: Serializing<UserComment>inFoo和Serializing<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;

    }


}

这里的Serializing对象是相同的,但是每个bean在其上声明一个不同的泛型。

因此,它将破坏泛型类型的类型安全性。


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


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


在Spring 4之前,您还具有其他解决方法来接受Bean依赖项中的泛型类型。

真正的问题是,@Service当它是必须配置为Bean的该泛型类的实例时,您为该泛型类添加了注释, 以使其成为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>();

    }

}

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


@Service

public class NoteController {


    private Serializing<UserComment> userCommentSerializer;


    @Autowired

    public NoteController(Serializing<UserComment> serializer) {

        this.userCommentSerializer = serializer;


    }

}


查看完整回答
反对 回复 2021-04-21
?
天涯尽头无女友

TA贡献1831条经验 获得超9个赞

您必须告诉Spring您要它自动连线的所有bean。没有例外。

如果您无法事先将其拼写清楚,那么我想说它不是注射的候选人。

您需要完全控制和通话的某些内容new。也许您的情况就是其中之一。这没什么不对的。这仅表示Spring DI不适合该用例。


查看完整回答
反对 回复 2021-04-21
  • 3 回答
  • 0 关注
  • 149 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信