Skip to main content

Spring

Wikipedia: The Spring Framework is an open source application framework and inversion of control container for the Java platform.
Это Container, так как Spring управляет жизненным циклом всех объектов контейнера: создает их и связывает (wiring) их друг с другом.
Это Framework, Spring позволяет создавать и конфигурировать сложные приложения из простых компонент, предоставляя гибкие и эффективные реализации многих необходимых сервисов.

1. DI и IoC Фаулер считает одним и тем же, просто DI - более подходящий термин. Паттерн DI предоставляет компоненту внешнюю зависимость (вместо того, чтобы захардкодить её). То есть мы сообщаем объекту о его зависимостях вместо того, чтобы он сам о них знал.
Предыстория: Мы стараемся использовать интерфейсы, например tree.getFruits(), но где мы создаем объект tree? Если в классе, который его использует, то получается, что класс зависит не только от интерфейса ITree, но и от конкретной реализации, скажем AppleTree. А если кто-то захочет использовать BananaTree?
Решение: Иметь некий объект - assembler - который будет инициализировать поле tree конкретной реализацией (через сеттер или конструктор).

2. Из чего состоит Spring (картинка взята с docs.spring.io) :
spring overview
3. IoC Container создает бины и внедряет (injects) в них зависимости. BeanFactory обеспечивает конфигурацию и управление объектами. ApplicationContext (интерфейс, расширяющий BeanFactory) добавляет resource handling (для I18n), event publication, AOP features. в Spring это тип BeanFactory. Можно сказать, что BeanFactory - основная функциональность, ApplicationContext - добавляет enterprise-specific функциональность. Как оно выглядит:
container magic

Configuration Metadata может быть xml-based, annotation-based или java-based.

Например, xml-конфигурация (а конфигурация - это указания для spring, какие компоненты создать и как их собрать) может выглядеть так:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans.xsd">

 <bean id="..." class="...">
 <!-- collaborators and configuration for this bean go here -->
 </bean>
 <bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
 <property name="accountDao" ref="accountDao"/>
 <property name="itemDao" ref="itemDao"/>
 <!-- additional collaborators and configuration for this bean go here -->
 </bean>
 
 <!-- more bean definitions go here -->

</beans>

Тогда создание контейнера (если xml-файлы - это файлы конфигурации):
// create and configure beans
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
// retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class);

DI через setter'ы:
<bean id="exampleBean" class="examples.ExampleBean">
 <!-- setter injection using the nested <ref/> element -->
 <property name="beanOne"><ref bean="anotherExampleBean"/></property>
 <!-- setter injection using the neater ref attribute -->
 <property name="beanTwo" ref="yetAnotherBean"/>
 <property name="integerProperty" value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>

DI через конструктор:
<bean id="exampleBean" class="examples.ExampleBean">
 <!-- constructor injection using the nested <ref/> element -->
 <constructor-arg>
 <ref bean="anotherExampleBean"/>
 </constructor-arg>
 <!-- constructor injection using the neater ref attribute -->
 <constructor-arg ref="yetAnotherBean"/>
 <constructor-arg type="int" value="1"/> 
</bean> 
<bean id="anotherExampleBean" class="examples.AnotherBean"/>

Контейнер проверяет конфигурацию всех бинов сразу после создания контейнера. Но созданы зависимости будут только при создании бина. По-умолчанию, бины являются Singleton и pre-instantiated. То есть, буду созданы тоже сразу после создания контейнера (контекста).

Beans scopes: singleton, prototype (создается новый объект при каждом обращении), request / session / global session - имеют смысл только если контекст имеет отношение к web.

4. Spring MVC
Как и в других Web фреймворках, Spring использует сервлет DispatcherServlet для управления всеми входящими запросами (этот шаблон еще называют Front controller).

web.xml:
<servlet>
 <servlet-name>MVC Dispatcher</servlet-name>
 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
 <servlet-name>MVC Dispatcher</servlet-name>
 <url-pattern>*.htm</url-pattern>
</servlet-mapping>

В web.xml файле, мы определили servlet mapping (соотнесли), который реагирует на любой URL, заканчивающийся на .htm. Если .htm встретилось, мы переходим на DispatcherServlet. Этот сервлет анализирует входящие запросы URL и определяет, какому контроллеру передать управление.

<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
Если нет * в url-pattern, то контейнер знает, что реквесты без path info (без .xxx) должны быть направлены DispatcherServlet'у. То есть, когда придет запрос на xxx.jsp, DispatcherServlet не будет реагировать.

Как оно выглядит в графическом виде? (Взято с Spring Recipes)
DispatcherServlet = Front Controller
Handler Mapping = Map of url and controllers


5. Контексты
Spring позволяет определить несколько контекстов. Они образуют иерархию предок-потомок. Контекст applicationContext.xml определяет бины для всего web-приложения. Контекст spring-servlet.xml определяет бины для одного Spring сервлета (за все контроллеры отвечает этот контекст). Бины из spring-servlet.xml могут обращаться к бинам из applicationContext.xml, но не наоборот.

Создание applicationContext: ContextLoaderListener это ServletListener. Он будет вызван при создании ServletContext'а для этого web-приложения. При вызове внутри ContextLoaderListener создается ApplicationContext и загружается конфигурационный xml (задается через context-param в web.xml). В этом конфигурационном файле (по логике вещей) не должно быть бинов связанных с web-слоем).

DispatcherServlet в его init методе тоже создает ApplicationContext, который должен загружать Controller'ы, ViewResolver'ы, MappingHandler'ы.

Бины из web tier видят бины уровня middle-tier, но не наоборот.

В простых случаях можно обойтись только контекстом из DispatcherServlet, но если есть что-то из нижеперечисленного, то не получится:
- несколько DispatcherServlet, которые разделяют сервисы
- legacy/non-Spring servlets, которым нужны бины
- есть сервлетные фильтры (Spring Security's DelegatingFilterProxy, OpenEntityManagerInViewFilter, ...)

TODO: Способы декларирования транзакций, когда можно проксировать классы, что будет при циклических зависимостях в контейнере.

  P.S. Пара ссылок http://nikcode.blogspot.ru/2011/09/spring-2-rest-spring-web-mvc.html
http://www.devlogg.com/2011/08/spring-mvc.html
http://www.tutorialspoint.com/spring/spring_interview_questions.htm

Comments

Popular posts from this blog

Блочный, строчный, ...

Сборник советов: 1. Прижать элемент к нижнему краю контейнера: 2 . Две колонки: 3 . Что означает символ ">" в селекторе? Означает, что будут выбраны только прямые потомки. По-умному, direct descendant combinator. Иными словами, если есть: То "div a {color: blue;}" изменит цвет всех ссылок, а "div > a {color: blue;}" - только первой и третьей. 4 . TODO

Hibernate

1. Hibernate Session . Javadoc называет её главным интерфейсом между java-приложением и Hibernate. Иногда её называют единицей работы или логической транзакцией. Основная функция сессии - обеспечить операции создания, чтения, удаления объектов. Объекты могут находиться в одном из 3 состояний (см. 2) Сессия создается с помощью SessionFactory. SessionFactory знает конфигурацию ORM, её внутреннее состояния immutable. При вызове Configuration().configure() загружается файл hibernate.cfg.xml. После того, как конфигурация загружена, можно изменить настройки программно. Данные корректировки возможны только до создания экземпляра фабрики сессий. // Initialize the Hibernate environment Configuration cfg = new Configuration().configure(); // Create the session factory ServiceRegistryBuilder srb = new ServiceRegistryBuilder(); ServiceRegistry sr = srb.applySettings(cfg.getProperties()).buildServiceRegistry(); SessionFactory factory = cfg.buildSessionFactory(sr); // Obtain the new session obj...

Первые шаги в Selenium

Цель расплывчата: понять и сделать хоть что-нибудь =) Selenium Selenium - группа продуктов. Отличное описание в статье Что такое Selenium? Selenium IDE - плагин для Firefox, позволяет записать тест, выполняя действия в браузере. Казалось бы, Selenium WebDriver должен дать больше возможностей: всё таки не из графического интерфейса тесты пишем, а с помощью языка программирования, но интересная мысль в другой статье того же автора  Что такое Selenium WebDriver? : "... WebDriver не имеет прямого отношения к тестированию. Он всего лишь предоставляет автотестам доступ к браузеру. На этом его функции заканчиваются.Структурирование, группировку и запуск тестов, а также генерацию отчётов о тестировании, обеспечивает фреймворк тестирования, такой как JUnit или TestNG для Java, .."  Локаторы Выбрать элемент на странице можно используя локаторы. Локаторы (в Selenium IDE в поле target) используют DOM, XPath или CSS (или просто ищут по id/name). Полезное: XPath: XML Path La...