【问题标题】:Bean singleton, session creation and initializationBean单例,会话创建和初始化
【发布时间】:2018-06-29 16:29:28
【问题描述】:

我不知道这是否是实施我的解决方案的更好方法:

@Component
@Scope("singleton")
public class GetFromJson implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = -8203722696439228358L;
    Map<String, Map<String, ArrayList<String>>> jsonMap;

    public Map<String, Map<String, ArrayList<String>>> getJsonMap() { 
        return jsonMap;
    }

    public void setJsonMap(Map<String, Map<String, ArrayList<String>>> jsonMap) {
       this.jsonMap= jsonMap;
    }    
}

该类是可序列化的,因为我从数据库中的 Json 获取内容并将内容映射到 Object GetFromJson 中(我只需要在数据库中进行一次查询)。出于这个原因,我需要在我的所有应用程序中使用对象,因此我认为我需要使用单例

有人向我发布了一个库以从数据库中获取 JSON。 JSON 对象解析为Map&lt;String, Map&lt;String, ArrayList&lt;String&gt;&gt;&gt;,因此我创建了我的GetFromJson 类。

现在我有很多休息服务,在我的休息服务中我需要使用我的对象:GetFromJson 来获取 jsonMap 的内容。

我有很多问题。

使用注释@Scope("singleton") 我保证GetFromJson 在我的所有应用程序中只有一个实例可用?

或者在 Spring 中让我的应用程序中可用的单例和会话对象的更好方法是什么?

使用GetFromJson获取jsonMap的内容就够用了

@Autowired
private GetFromJson jsonObject;

或者我怎样才能获得我的单身课程?

在我的休息方法服务中使用:

 jsonObject.getJsonMap();

如何初始化我的单例,因为我正在尝试使用以下方法初始化我的对象:

@Autowired
private GetFromJson jsonObject;


public methodToInitialize(){
    jsonObject = methodLibraryFromDatabase(GetFromJson.class);
}

IDE 告诉我没有使用字段初始化

我需要相同的逻辑,但是对于会话对象,我认为如果我理解会话对象的单例实现将是相同的,但只需将注释更改为:@Scope("session")

【问题讨论】:

    标签: java spring spring-mvc spring-boot


    【解决方案1】:

    我认为 OP 想要在应用程序生命周期中初始化一次基于数据库的 POJO 并在需要的地方自动装配它。

    通常这是通过创建一个 bean(除非另有说明,它们是单例)并在需要时自动装配它来完成。

    此示例应该可以帮助您入门。

    @Configuration // beans are declerated in @Configuration classes
    public class GetJsonInitializer {
    
        @Bean // singleton by default
        public GetFromJson jsonMap(){
            GetFromJson jsonObject = methodLibraryDatabase(GetFromJson.class);
            return jsonOBject;
        }
    }
    

    现在在任何 Spring 服务/组件等中自动装配 GetFromJson

    @Service
    public class SomeService {
        @Autowired
        private GetFromJson jsonMap;
    }
    

    希望这会有所帮助!

    【讨论】:

    • 好的。我明白。如果我使用 scope("session") @Bean @scope("session") public GetFromJson jsonMap(){ 将注释添加到 Bean,它会改变 bean 的范围?
    • 是的。在每个新会话中注入一个新创建的 bean woukd
    • 不,我正在尝试,但它告诉我:当前线程的范围“会话”不活动;如果您打算从单例中引用它,请考虑为该 bean 定义一个作用域代理;
    • Scope 会话仅适用于 Web 服务。这也可以帮助你stackoverflow.com/a/21358274/776548
    【解决方案2】:

    使用会话范围注释的 bean 将绑定到用户的会话生命周期,也就是说,对于每个访问您的应用程序的用户,您将拥有此类的一个实例。如果您想保证在您的应用程序(在 JVM 级别)中只有一个该 bean 的实例,您只需要删除 @Scope 注释。但是,如果您想将单例与会话范围 bean 混合,那么您应该让 spring 为您无缝处理所有事情,您的会话范围 bean 只会在用户会话结束时被销毁。

    在 bean 中处理初始化代码的最佳方式是使用带有 javax.annotation.PostConstruct 注释的公共方法

    @PostConstruct
    public void setUp() {
        //initialization code
    }
    

    为了在 bean 将要被销毁时处理清理代码,您应该让您的类实现 org.springframework.beans.factory.DisposableBean 或添加一个带有 javax.annotation.PreDestroy 注释的方法

    @PreDestroy
    public void onDestroy() {
        //clean up code
    }
    

    希望对你有所帮助!

    【讨论】:

    • 并在restService中使用Autowired创建实例?我可以在不同的服务中使用注入来更改对象实例吗?
    • 如果 bean 是会话范围的,spring 将在需要时创建和更改实例引用。但是,如果您想要更短的生命周期,也就是说,对于每个引用总是一个新实例,您应该寻找原型作用域 bean 和工厂 bean。如果您想自己创建实例,@Archit 的下一个答案可以指导您如何正确地创建实例。此外,还有其他方法可以像这样强制销毁 bean:stackoverflow.com/a/22746820/3335350
    猜你喜欢
    • 1970-01-01
    • 2013-05-22
    • 1970-01-01
    • 2014-12-19
    • 1970-01-01
    • 1970-01-01
    • 2015-07-23
    • 2014-09-19
    • 1970-01-01
    相关资源
    最近更新 更多