有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何避免Spring托管bean和Pojo依赖于同一服务时出现单例

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

  • 有/有使用某些实用程序服务的Spring管理bean
  • 存在/存在使用相同公用事业服务的POJO
  • 服务的实现应该易于模拟/交换

JacksonMapper实现JsonStringConverter接口

POJO是一些由构建器模式创建的自定义对象,如下面的示例,它使用接口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管理的,因此我无法将JsonStringConverter的实现注入带有@Autowire注释的用户

另一方面,有些Spring托管bean使用该接口的相同实现将一些其他映射转换为Json字符串。但由于我已经在SpringIOC外部缓存了一个converter实例,而不是在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与静态方法一起从Json转换为Json。Spring管理的bean和POJO现在可以使用该实用程序类而不是单例

缺点:我更喜欢在JsonStringConverter和客户机代码之间使用显式接口,以便于模拟和交换实现

  • 使用单例模式

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

有人能给我指出第三种合理的选择吗

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


共 (1) 个答案

  1. # 1 楼答案

    只需将你的单身汉注册为Spring bean:

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

    注意,在这样的情况下,建议将JacksonMapper作为enum模式的一部分,而不是普通类