На днях Суровый выложил на GitHub исходники и некоторые результаты небольшого бенчмарка, проверяющего гипотезу о том, что Spring Framework быстрее этих ваших EJB.
Как оказалось - нет, не быстрее.
Для тестирования был выбран кейс, представленный Адамом Бином в его вебкасте What Is Faster--EJBs Or CDI? A JMH Benchmark: были разработаны три реализации простейшего RESTful веб-сервиса, с использованием Spring Framework, CDI и EJB, соответственно. Конструкция сервисов в общем случае напоминает архитектуру корпоративного приложения: в контроллер инжектируется сервис, в который в свою очередь инжектируются два ресурса (этакие "DAO").
Пример кода с использованием EJB:
Каждая технология использовалась самым очевидным, т.е. распространенным, принятым в сообществе пользователей данной технологии, способом.
Как оказалось - нет, не быстрее.
Описание эксперимента
Для тестирования был выбран кейс, представленный Адамом Бином в его вебкасте What Is Faster--EJBs Or CDI? A JMH Benchmark: были разработаны три реализации простейшего RESTful веб-сервиса, с использованием Spring Framework, CDI и EJB, соответственно. Конструкция сервисов в общем случае напоминает архитектуру корпоративного приложения: в контроллер инжектируется сервис, в который в свою очередь инжектируются два ресурса (этакие "DAO").
Пример кода с использованием EJB:
@Stateless public class EJBResourceA { public String message() { return "A#" + System.currentTimeMillis(); } } @Stateless public class MessageService { @EJB private EJBResourceA aresource; @EJB private EJBResourceB bresource; public String message() { return aresource.message() + bresource.message(); } } @Stateless @Path("/") public class MessageController { @EJB private MessageService service; @GET @Path("/message") @Produces({"text/plain"}) public String message() { return service.message(); } }
Каждая технология использовалась самым очевидным, т.е. распространенным, принятым в сообществе пользователей данной технологии, способом.
- Для Spring Framework в качестве основы реализации RESTful веб-сервиса был взят Spring MVC: запросы обрабатываются с помощью DispatcherServlet, к которому подключается MessageController, аннотированный RestController, что говорит фреймворку возвратить результат метода MessageController#message() в теле ответа сервиса. В данный контроллер с помощью аннотации Autowired инжектируется сервис, в который, в свою очередь, аналогичным образом инжектируются два компонента-ресурса. Конфигурация контекста приложения (Spring Framework ApplicationContext) осуществляется с помощью аннотаций:
@Configuration @ComponentScan(basePackageClasses = ApplicationConfig.class) @EnableWebMvc public class ApplicationConfig { }
Регистрация слушателей, осуществляющих загрузку контекста, а так же настройка DispatcherServlet'а осуществляется в классе, реализующем интерфейс org.springframework.web.WebApplicationInitializer:
public class ApplicationInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext(); applicationContext.register(ApplicationConfig.class); servletContext.addListener(new ContextLoaderListener(applicationContext)); ServletRegistration.Dynamic dispatcher = servletContext.addServlet("spring-mvc-dispatcher", new DispatcherServlet(applicationContext)); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/api/*"); } }
- Для CDI: все компоненты создаются в области видимости по-умолчанию - Dependent.
- Для EJB: все классы аннотированы @Stateless, что соответствует наиболее популярному типу - сессионным компонентам без сохранения состояния. Для хранения экземпляров компонентов используется пул, предоставляемый контейнером EJB сервера приложений. Так же очень важный момент - управление транзакциями. По-умолчанию, EJB-контейнер берет на себя управление транзакциями при обращении к компоненту, при этом если вызов бизнес-метода компонента осуществляется вне контекста глобальной транзакции, то такая транзакция будет создана. Можно было отключить использование данного механизма, тогда условия тестирования больше бы соответствовали режимам, в которых работают конкуренты, но для следования озвученному выше критерию - технология используется наиболее распространенным способом - этого сделано не было.