在SpringMVC服务中进入方法并退出该方法花费了太多毫秒。但是,如果我将方法修改为静态,则只需花费1毫秒的时间。 我们的项目是SpringMVC-Mybatis项目,我发现控制器进入服务方法并从该方法退出大约花费70毫秒。 该方法从具有128个键的静态映射中获取值。
@Controller
public class OrdersController extends BaseAction
{
@Autowired(required=false)
private CompanyService<Company> companyService;
public void validateInfo()
{
Company company = CompanyService.queryByIdFromCache(account);// cost about 70 milliseconds, but if the method is static it is 1 milliseconds.
}
@Service("companyService")
public class CompanyService<T> extends BaseService<T>
{
private static ConcurrentMap<Integer, Company>cache = new ConcurrentHashMap<>(); //map with 128 keys
public Company queryByIdFromCache(Integer id)
{
return cache.get(id);
}
}
我希望方法在2毫秒内完成。 该服务在单例模式下工作。和companyService是同一实例。 我不想将所有方法都修改为静态方法,因为某些代码必须以非静态方式调用。
答案 0 :(得分:0)
某个方面可能正在拦截对非静态服务方法的调用。
有几种方法可以分析执行情况并找到服务呼叫的热点。我使用NetBeans的Test Profiler来复制此问题。
首先,我创建了静态(组件)和非静态服务:
@Service
public class DemoService {
private static final ConcurrentMap<Integer, String> CACHE = new ConcurrentHashMap<>();
public DemoService() {
for (int i = 0; i < 128; i++) {
CACHE.put(i, String.valueOf(i));
}
}
public String queryByIdFromCache(Integer id) {
return CACHE.getOrDefault(id, "");
}
}
public class DemoStaticService {
private static final ConcurrentMap<Integer, String> CACHE = new ConcurrentHashMap<>();
static {
for (int i = 0; i < 128; i++) {
CACHE.put(i, String.valueOf(i));
}
}
public static String queryByIdFromCache(Integer id) {
return CACHE.getOrDefault(id, "");
}
}
然后我创建了一个控制器,该控制器具有两个操作,一个调用非静态注入服务,另一个调用使用静态方法的服务:
@RestController
@RequestMapping(path = "/demo")
public class DemoController {
@Autowired
private DemoService demoService;
@GetMapping(path = "/demo")
public String callService(@RequestParam Integer id) {
return demoService.queryByIdFromCache(id);
}
@GetMapping(path = "/static-demo")
public String callStaticService(@RequestParam Integer id) {
return DemoStaticService.queryByIdFromCache(id);
}
}
之后,我编写了两个单元测试来帮助我分析服务方法:
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoControllerTest {
@Autowired
private DemoController demoController;
@Before
public void before() {
demoController.callService(1);
demoController.callStaticService(1);
}
@Test
public void testCallService() {
for (int id = 0; id < 128; id++) {
demoController.callService(id);
}
}
@Test
public void testCallStaticService() {
for (int id = 0; id < 128; id++) {
demoController.callStaticService(id);
}
}
}
打开测试文件后,我选择了Profile -> Profile Test File
菜单项:
然后从▶ Profile
下拉菜单中,选择了Methods
选项:
最后,我单击了▶ Profile
按钮以配置测试。我得到了这个结果,表明对注入服务的调用仅比对静态方法的调用贵50%:
但是如果第二种方法被某个方面(例如@Transactional
)拦截了怎么办?
为了对此进行测试,我更新了DemoService
并使它的方法具有事务性
@Service
public class DemoService {
private static final ConcurrentMap<Integer, String> CACHE = new ConcurrentHashMap<>();
public DemoService() {
for (int i = 0; i < 128; i++) {
CACHE.put(i, String.valueOf(i));
}
}
@Transactional
public String queryByIdFromCache(Integer id) {
return CACHE.getOrDefault(id, "");
}
}
重新运行测试后,这次我得到了此分析结果:
可以看出,事务方面使DemoService.queryByIdFromCache
的调用速度降低了14.5(10.2 / 0.708)倍。
要找到导致服务方法变慢的根本原因,建议您设置类似的测试并使用NetBeans Profiler(或类似工具)对其进行分析。