为了优化sql请求,我创建了一个聚合其他服务消耗的服务,以避免不必要的调用。(我的webapp应用程序的某些页面每天被调用数百万次,因此我希望在每个请求中尽可能多地重用数据库查询的结果)
我创造的解决方案是这个:
我的服务有@RequestScope,而不是默认范围(Singleton)
在MyService中
@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;
}
}在我的控制器里:
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();
}
} 当然,我简化了我的示例,因为myService使用了许多其他元素,并且我保护他的成员属性的初始化
该方法的优点是只在需要属性时延迟加载它们。如果在我的项目中的某个地方(在相同或其他控制器中)我只需要SecondTextPres,那么调用"getSecondTextPres“将初始化两个列表--在我的示例中不是这样--因为第一个列表是在调用"getMainTextPres”时初始化的。
我的问题是:
非常感谢!
朱利安
发布于 2016-09-26 11:17:57
我认为你的想法是行不通的。如果您调用相同或不同的控制器,这将是不同的请求--在这种情况下,将创建新bean (元素和其他元素再次为空)。
你有没有考虑过缓存?Spring提供了很好的支持,您可以在其中定义缓存过期等。
发布于 2016-09-26 11:24:37
我不太清楚您到底想在请求范围内优化什么?如果您对内存脚印感到烦恼,您可以很容易地通过JMX或VisualVM来测量它。
另一方面,您可以使所有服务调用都是纯的,即依赖于函数参数和(ofc)数据库状态,并将默认作用域实例化为Singleton。
这个决定将为您节省合理的资源,因为您不会在每个调用上实例化可能的大型对象图,并且在请求完成后不需要GC来清理。
经验法则是考虑为什么需要在每个调用上实例化特定的类,如果它没有保持任何特定的调用状态,那么就让它成为Singleton。
说到懒惰加载,总是有助于思考最坏的情况重复了100次。它是否真的为您节省了与加载一次和整个容器生命周期相比较的东西。
https://stackoverflow.com/questions/39701043
复制相似问题