Spring 3: что нового
Александр Яризов, сертифицированный специалист Sun Mycrosystems
Spring 3.0: что нового.
С самого начала своего появления на свет основными особенностями платформы Spring являлись поддержка конфигурирования зависимостей (dependency injection-DI или inversion of control-IoC), аспектно-ориентированного программирования и абстракции сервисов (Enterprise Service Abstraction), что и до настоящего времени является уникальным и единственным в своем роде продуктом. Главным новшеством последней на настоящее время версии 2.5 является появление возможности использования Java аннотаций для определения и конфигурирования Java Beans, что в предыдущих версиях это можно было делать только с помощью XML.
Хотя опыт применения Spring 2.5 показал, что для некоторых проектов невозможно использование аннотаций, поскольку для этих проектов предусловием явлалась необходимость использования JDK 1.4, однако было принято решение, что для использования Spring 3.0 необходимым условием является JDK версии не менее 1.5. Одной из основных причин такого решения является решение компании Sun больше не поддерживать JDK 1.4.
Аннотации или XML?
Среди разработчиков, использующих платформу Spring, существуют как бы два лагеря, одни считают, что для конфигурирования Java Beans лучше использовать XML, аргументирующих свое предпочтение прежде всего тем, что исходный Java код должен быть свободен от различных технических деталей, в то время как другие ратуют за более широкое использование аннотаций. Конечно нет однозначного ответа, когда и какой метод лучше использовать, в каждом конкретном проекте решение может и должно быть принято индивидуально, однако в некоторых случаях использование аннотаций является предпочтительным, например:
* Аннотации значительно упрощают жизнь разработчика при реализации юнит тестов (unit tests) используя JUnit4 и TestNG. Рассмотрим следующий пример:@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={“/configuration.xml“})
@Transactional
public class OrderTest {
@Autowired
private ClientDAO clientDAO;
@Resource(name=”realOrderDAO”)
private OrderDAO orderDAO;
@Test(expected=OrderException.class)
public void testEmptyShoppingCart() throws OrderException {
….
}
}
Аннотация @RunWith активирует поддержку Spring на этапе исполнения, конфигурационный файл задается с помощью аннотации @ContextConfiguration. Затем аннотированы две приватных переменных класса OrderTest, одна с помощью аннотации @Autowired, которая означает что в контексте Spring будет найден bean типа ClientDAO и связан с переменной clientDAO, другая переменная orderDAO будет связана по имени, т.е. в контексте будет найден bean с именем realOrderDAO, как это указано с помощью аннотации @Resource.
Кроме того, как видно из указанного примера, аннотацией @Test(expected=OrderException.class) устанавливается, что результатом работы метода testEmptyShoppingCart должно быть исключение (exception) типа OrderException
Как видно из приведенного примера, для каждого члена класса можно отдельно указать, каким образом Spring связывает его с соответствующим bean из окружения, по имени или по типу, что было невозможно используя JUnit3, где тип связывания задается единообразно для всех членов класса. Поэтому в Spring 3.0 классы, осуществляющие взаимодействие с JUnit3 хотя и сохранились, упоминание о них изъято из документации и сопровождение этих классов в дальнейшем не будет оказываться.
* С помощью аннотаций упрощается определение контроллеров для web приложений. Рассмотрим следующий пример
@Controller
@RequestMapping(value=“/clientcreate“)
public class ClientCreateController {
@RequestMapping(method=RequestMethod.GET)
public ModelAndView showForm() {
…
}
@RequestMapping(method=RequestMethod.POST)
protected ModelAndView handlePost(@ModelAttribute(“client”) Client client
) {
…
}
}
Здесь определен класс, который связан с URL / clientcreate, что определено аннотацией @RequestMapping на уровне класса. При запросе типа HTTP GET будет возвращен пользователю форма запроса, поскольку метод showForm содержит соответствующую аннотацию, заполненная пользователем форма обрабатывается впоследствии методом handlePost, так как этот метод реагирует на запросы HTTP POST. Подобное поведение в точности соответствует подходу, который был ранее реализован в классе SimpleFormController. Для реализации более сложного случая с помощью класса SimpleFormController необходимо детальное знание реализации этого класса, для того, чтобы перегружать соответствующие методы.
Несомненно подход, предлагающий использование аннотаций, является значительно более прозрачным и легким, поэтому в Spring 3.0 рекомендовано использовать аннотации, а сам класс SimpleFormController более не поддерживается.
Spring 3.0 и Web
Новая версия Spring включает определенные новшества также и в области Web. Прежде всего это касается поддержки «разговора» (Conversation), т.е. позволяет сохранять значения переменных web-приложения в на протяжении нескольких страниц. Например процесс регистрации на каком-нибудь ресурсе для поиска работы может потребовать заполнения личной информации, домашнего адреса, истории трудовой деятельности, информацию о полученном образовании и многое другое. Хотя все эти данные возможно сохранять (и часто реализуется именно таким образом) в текущей сессии (HTTP Session), при использовании такого подхода необходимо было всегда учитывать, что сессия создается для 1 пользователя и в случае параллельной обработки (например сотрудник бюро по трудоустройству стал вносить данные об одном соискателе, обнаружил отсутствие какой-нибудь информации, запросил ее и пока ожидает, начал вносить данные о другом) необходимо было принимать дополнительные мере для предотвращения наложения или переписывания введенных данных. При «разговоре» каждый пользователь может создавать несколько независимых друг от друга цепочек и одновременная обработка больше не является проблемой. Кроме того, «разговор» хорошо комбинируется с объектно-реляционными мапперами (Object-Relational Mapping), например Hibernate или JPA: изменяемые данные накапливаются в кэше (cache) маппера, который в свою очередь связан с «разговором». По окончанию «разговора» накопленные в кеше изменения записываются в базу данных. При этом нет необходимости в начале каждого «разговора» заново создавать каждый кэш, нужно только заботиться о том, чтобы в конце «разговора» данные были сохранены.
Понятие «разговора» существует также в проекте Spring Web Flow. В будущем Spring Web Flow будет использована реализацию этой функциональности основного проекта. Spring Web Flow характеризуют также и другие отличительные свойства, например возможность моделировать последовательность прохождения web-страниц при помощи графического редактора или в XML, также наличием собственного фреймворк и благодаря этому возможностью использовать Spring Web Flow для навигации в JSF приложениях, причем в этом случае JSF-компоненты управляются Spring Web Flow.
Еще одно новшество в области Web в Spring 3.0 является поддержка нового стандарта Portlet 2.0 (JSR286). Spring уже достаточно давно поддерживает стандарт Portlet 1.0 (JSR168) и реализация нового стандарта позволяет использовать все преимущества, которые им предусмотрены.
Еще одной особенностью, которая хоть и не связана напрямую с Web представлением, будет тем не менее в нем широко использоваться разработчиками, является предусмотренная поддержка стандарта JSR303 (Bean Validation), определяющий API для проверки правильности введенных данных и соответствия этих данных неким бизнес правилам.
Expression Language - EL.
Spring 3.0 привнес одно новшество, которое будет иметь огромное влияние на последующую разработку и сопровождение реализованных с использованием Spring приложений– в новой версии добавлена поддержка языка выражений (expression language), с помощью которого появляется возможность конфигурации компонентов (Spring Beans), а не только задания простых значений.
Пример использования языка выражений приведен в следующем примере:
<bean class=“com.package.ClassUsingDatabase“>
<property name=”database” value=”#{properties.database}”/>
<property name=”username” value=”#{properties.username}”/>
<property name=”password” value=”#{properties.password }”/>
</bean>
Выражение начинается с символа # и заключается потом в фигурные скобки. Далее идет обращение к различным свойствам компонента (bean) с именем properties, причем существует возможность комбинировать различные свойства используя арифметические операторы, применяя их как параметры функций или же наоборот, вызывая методы этого компонента. Используя EL можно получить не только отдельные свойства компонента, но также и отдельные элементы некоторой коллекции, например списка (List) или таблицы (Map). Аналогичным образом можно получить доступ к значениям HTTP Request или HTTP Session при конфигурировании Web приложений.
Применение EL не ограничивается только конфигурационным файлом, язык выражений можно также использовать в аннотациях классов, как например это сделано в следующем примере:@Repository
public class ClassUsingDatabase {
@Value (“#{properties.database})
public void setDatabase(String database) {…}
@Value (“#{properties.username })
public void setUsername (String username) {…}
@Value (“#{properties.password })
public void setPassword (String password) {…}
}
Используя язык выражений в аннотациях, разработчик получает выигрыш например в том, что при изменении параметров доступа к базе данных нет необходимости перекомпилировать исходный java файл, достаточно изменить значения в конфигурационном файле.
Другие новшества
Одним из важных сделанных в Spring 3.0 изменений является новая структура проектов. Начиная с версии 3.0, больше не существует одного всеобъемлющего файла spring.jar, включающего в себя все составные части, а разбит на отдельные модули, каждый из которых представляет для пользователя отдельный jar файл. За счет этого шага более естественным и обоснованным является применения новых технологий и инструментов, например таких Maven или OSGi, которые могут быть использованы для загрузки и использования зависимых библиотек.
В Spring 3.0 реализована поддержка новых J2EE-6 технологий JSF2, JSR236, JPA 2.0, интерцепторы (interceptors) JSR220 (EJB 3.0) (хотя они и не предоставляют таких же обширных возможностей, как Spring AOP) и определяемой этим стандартом аннотации @Transactional, также как описанных в стандарте JSR250 (Common Annotations) аннотаций @PreDestroy, @PostConstruct, @Resource, @RollesAllowed
В тоже время была изъята поддержка таких технологий как Oracle Toplink API, поскольку этот интерфейс был замещен JPA, или Jakarta Commons, замещенной Java Annotations. Сделано это было, чтобы не перегружать устаревшими интерфейсами и чрезмерно не усложнять Spring.
Планируется в скором времени обеспечить поддержку новому стандарту JSR299, носящим первоначально название «Web Beans», однако переименованным недавно в «Java Context and Dependency Injection», и реализация поддержки нового стандарта Servlet 3.0.