Java Spring4@Service和@RequestScope

Java Spring4@Service和@RequestScope,java,spring,spring-mvc,service,scope,Java,Spring,Spring Mvc,Service,Scope,为了优化sql请求,我创建了一个服务来聚合其他服务消耗,以避免不必要的调用。 (我的webapp的某些页面每天被调用数百万次,因此我希望在每次请求时尽可能多地重用数据库查询的结果) 我创建的解决方案是: 我的服务使用@RequestScope而不是默认范围(Singleton) 为我服务 @Service @RequestScope public MyService { private int param; @Autowired private OtherService otherServi

为了优化sql请求,我创建了一个服务来聚合其他服务消耗,以避免不必要的调用。 (我的webapp的某些页面每天被调用数百万次,因此我希望在每次请求时尽可能多地重用数据库查询的结果)

我创建的解决方案是:

我的服务使用@RequestScope而不是默认范围(Singleton)

为我服务

@Service
@RequestScope
public MyService {

private int param;

@Autowired
private OtherService otherService;

@Autowired
private OtherService2 otherService2;

private List<Elements> elements;

private List<OtherElements> otherElements;

public void init(int param) {
    this.param = param;
}

public List<Elements> getElements()  {

    if(this.elements == null) {
        //Init elements
        this.elements = otherService.getElements(param);
    }

    return this.elements;

}

public List<OtherElements> getOtherElements()  {

    if(this.otherElements == null) {
        //Init otherElements
        this.otherElements = otherService2.getOtherElements(param);
    }

    return this.otherElements;

}

public String getMainTextPres() {

    //Need to use lElements;
    List<Elements> elts = this.getElements();

    ....

    return myString;

}

public String getSecondTextPres() {

    //Need to use lElements;
    List<Elements> elts = this.getElements();
    //Also Need to use lElements;
    List<OtherElements> otherElts = this.getOtherElements();        

    ....

    return myString;

}
}
当然,我已经简化了我的示例,因为myService使用了许多其他元素,并且我保护了其成员属性的初始化

这种方法的优点是只在需要属性时才延迟加载属性。 如果在我的项目中的某个地方(在同一个或其他控制器中),我只需要SecondTextPres,那么调用“getSecondTextPres”将初始化两个列表,这在我的示例中不是这样的,因为调用“getMainTextPres”时第一个列表已经初始化

我的问题是:

  • 你觉得这种做事方式怎么样
  • 由于我在每个请求上实例化了我的服务,可能会出现性能问题吗
非常感谢


朱利安我认为你的想法行不通。如果您调用相同或不同的控制器,这将是不同的请求-在这种情况下,将创建新的bean(元素和其他元素再次为空)


你有没有想过缓存?Spring提供了很好的支持,您可以在其中定义缓存过期,等等。我认为您的想法是行不通的。如果您调用相同或不同的控制器,这将是不同的请求-在这种情况下,将创建新的bean(元素和其他元素再次为空)


你有没有想过缓存?Spring提供了很好的支持,您可以在其中定义缓存过期等,我不太清楚您到底想在请求范围内优化实例化服务的是什么?如果您对内存足迹感到烦恼,可以使用JMX或VisualVM轻松测量它

另一方面,您可以使所有服务调用纯粹化,即仅取决于函数参数和(ofc)数据库状态,并使用默认范围将服务实例化为Singleton

这个决定将为您节省合理数量的资源,因为您不会在每次调用时实例化可能的大型对象图,也不需要GC在请求完成后清理对象

经验法则是思考为什么每次调用都需要实例化特定的类,如果它没有保留任何特定于调用的状态,则将其设置为Singleton


说到延迟加载,考虑最坏的情况重复100次总是有帮助的。与在整个容器生命周期中一次加载相比,它真的会为您节省一些东西吗

我不太清楚您到底想在请求范围内优化实例化服务的是什么?如果您对内存足迹感到烦恼,可以使用JMX或VisualVM轻松测量它

另一方面,您可以使所有服务调用纯粹化,即仅取决于函数参数和(ofc)数据库状态,并使用默认范围将服务实例化为Singleton

这个决定将为您节省合理数量的资源,因为您不会在每次调用时实例化可能的大型对象图,也不需要GC在请求完成后清理对象

经验法则是思考为什么每次调用都需要实例化特定的类,如果它没有保留任何特定于调用的状态,则将其设置为Singleton


说到延迟加载,考虑最坏的情况重复100次总是有帮助的。与在整个容器生命周期中一次加载相比,它真的会为您节省一些东西吗

为什么要用请求范围的bean来优化它呢。每个请求都有自己的实例,没有重用的内容。如果您真的想优化,请修复您的查询或使用缓存。我建议研究Spring能为您做些什么(以及如何缓存结果),而不是自己动手做。它是优化的,因为一个相同的请求会多次使用相同的低级信息,这种方式有助于我重用服务层上已有的数据。我不打算在两个不同的请求上对其进行优化。如果您在单个请求中需要这样的优化,您可能需要重新考虑您的流程。在一个请求中,只咨询一个控制器,其他所有的都是一个新请求。从你的描述来看,你似乎在试图优化一些你甚至没有测量过的东西,或者这确实是一个问题。看起来您正在尝试优化甚至不需要优化的内容。记住:过早优化是万恶之源。也许有更好(更容易?)的方法来改进事情,而不是引入范围。但首先要衡量,衡量,衡量。其次,如果数据被大量查询,当使用一个像样的数据库时,这将优化数据获取或优化查询。你是对的,我没有衡量标准。事实上,我知道这样做可以减少数据库调用,这就是我想这样做的原因,我的数据库服务器负载很重,所以如果我可以减少请求数量,这对我来说是件好事。但我知道我这样做的方式并不常见,这就是为什么我今天要问我的问题:)以及为什么要用请求范围的bean来优化它。每个请求都有自己的实例,没有重用的内容。如果您真的想优化,请修复您的查询或使用缓存。我建议研究Spring能为您做些什么(以及如何缓存结果),而不是自己动手做。它是优化的,因为一个相同的请求会多次使用相同的低级信息,这种方式有助于我重用服务层上已有的数据。如果您需要优化,我不打算在两个不同的请求上对其进行优化
public class myController {
@Autowired MyService myService;

@RequestMapping...
public ModelAndView myFunction(int param) {
myService.init(param);

String mainTextPres = myService.getMainTextPres();

String secondTextPres = myService.getSecondTextPres();

}

@OtherRequestMapping...
public ModelAndView myFunction(int param) {
myService.init(param);

String secondTextPres = myService.getSecondTextPres();

}
}