当 Spring managed bean 和 Pojo 依赖相同的服务时如何避免 Singleton

How to avoid Singleton when Spring managed bean and Pojo depend on same service

我正在寻找单例模式的替代设计,前提条件如下:

JacksonMapper 实现了 JsonStringConverter 接口。

POJO 是由 Builder 模式创建的一些自定义对象,例如下面的示例,它使用接口 JsonStringConverter.

的实现
public class User {

    private static final JsonStringConverter jsonStringConverter = JacksonMapper.getInstance();

    private String name;
    //...

    private User (User builder) {

       this.name = builder.name;
    }

    public String getName() {

        return name;
    }

    public String toJson() {

        Map<String, String> jsonMap = new LinkedHashMap<String, String>();

        jsonMap.put(UserAtributes.NAME.getDescription(), this.name);

        return jsonStringConverter.toJson(jsonMap);
    }

    public static class UserBuilder {

        private String name;
        //...


    public UserBuilder name(String name) {

        this.name = name;

        return this;
    }

    public User build() {

        return new User(this);
    }
  }
}

由于 User 的实例不受 Spring 管理,我无法使用 @Autowire 注释将 JsonStringConverter 的实现注入用户。

另一方面,有 Spring 托管 Bean 使用该接口的相同实现将一些其他映射转换为 Json 字符串。但是因为我已经有一个转换器实例缓存在 Spring IOC 之外,而不是在 IOC 内创建新对象只是为了注入,我还在 bean 中用 getInstance() 轮询它。这是我一点都不喜欢的部分。

这是有问题的单例:

public class JacksonMapper implements JsonStringConverter {

    private static final ObjectMapper jsonToMap;
    private static final ObjectMapper mapToJson;

    private static final JacksonMapper INSTANCE;

    static 
    {
        INSTANCE = new JacksonMapper();
        jsonToMap = new ObjectMapper();
        mapToJson = new ObjectMapper();
    }

   /**
    * Exists to defeat instantiation
    */
    private JacksonMapper() {
    // not called
    }

    public static JacksonMapper getInstance() {

        return INSTANCE;
    }

 // methods...
}

我现在看到的选项:

缺点: 我更愿意在 JsonStringConverter 和客户端代码之间使用显式接口,以便模拟和轻松交换实现的可能性。

缺点: 要求内存中有不必要的对象来调用本来应该是静态的方法。

有人可以为我指出上述情况的第三个合理选择吗?

请注意,当 Spring 托管 bean 和 POJO 都依赖于同一服务时,这是一般性问题,与此特定用例无关。

只需将您的单例注册为 Spring bean:

@Configuration
public class SingletonWrapperConfig {
    @Bean
    public JacksonMapper jacksonMapper() {
        return JacksonMapper.getInstance();
    }
}

请注意,在这种情况下,建议将 JacksonMapper 设为 enum 而不是普通的 class 作为 "enum singleton" 模式的一部分。