Java Spring4@Service和@RequestScope
为了优化sql请求,我创建了一个服务来聚合其他服务消耗,以避免不必要的调用。 (我的webapp的某些页面每天被调用数百万次,因此我希望在每次请求时尽可能多地重用数据库查询的结果) 我创建的解决方案是: 我的服务使用@RequestScope而不是默认范围(Singleton) 为我服务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
@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();
}
}