130
Промышленное программирование Сборка проекта

Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Embed Size (px)

Citation preview

Page 1: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Промышленное программирование

Сборка проекта

Page 2: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Использование готового кода

Page 3: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Утилитыpublic String join(String sep, Object… tokens) { StringBuilder sb = new StringBuilder(); for (Object token : tokens) { if (!sb.isEmpty()) { sb.append(sep); } sb.append(token); } return sb.toString();}

Page 4: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Утилитыimport com.google.guava....Joiner;

Joiner.on(“,”).join(anything);

Page 5: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Сборка и деплойcd myProjectjavac $(find src/ -name “*.java”)# Noo, what about classpath?export CLASSPATH=lib/...javac $(find src/ -name “*.java”)# Noo, what about cleaning?rm -rf target/javac $(find src/ -name “*.java”)# Noo, what about download some libraries?wget http://repo1.maven.org/maven2/log4j/log4j/1.2.17/log4j-1.2.17.jarjavac $(find src/ -name “*.java”)# Oh, sorry, no compiler for Java 8 =(# FFFFFFFFFFFUUUUUUUUUUUUU!!!!!1111

Page 6: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Сборка и деплойmvn clean install

Page 7: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

ИнициализацияService service = new ServiceImpl();FooHandler handler = new FastFooHandler(HANDLE_SPEED);service.setHandler(handler);int importantParameter = Integer.parseInt(args[1])service.setImportantParameter(importantParameter);Listener l1 = new LazyListener();Listener l2 = new DilligentListener();service.setListeners(Arrays.asList(l1, l2));service.init();

Page 8: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Инициализацияclass ServiceImpl implements Service { @Autowired Handler handler;

@Autowired List<Listener> listeners;

@Value(“#{args[1]}”) int importantParameter;

@PostConstruct void init() { … }}

Page 9: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

У Java очень большое сообществоВсе ваши задачи кто-то уже решилК любому сервису кто-то уже написал APIК каждому багу кто-то уже настругал

костыль workaround

Page 10: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Общие библиотекиПодробно документированыОбильно обсуждены на форумахПочти стабильно работаютДоступны для скачивания в репозиториях

Page 11: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Google GuavaОбертки над объектами и исключениямиНовые коллекции, Immutable-коллекцииФункциональщинаМногопоточностьКешированиеРабота со строкамиХеш-функцииРабота с потоками и файловой системойВолшебные Reflection

Page 12: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Apache CommonsРасширения для java.langНовые коллекцииПотоки и файловая системаАлгоритмы кодирования и хешированияСжатие и распаковкаConnection Pooling…

Page 13: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Логгингjava.util.logging (JUL)Apache commons-loggingLog4jSLF4jLogback

Page 14: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

ТестированиеJUnitTestNGUnitilsMockitoJMockSpring Test *…

Page 15: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Как подключить библиотеку?

Page 16: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Apache MavenMaven - “фреймворк для автоматизации

сборки проектов...” (с) WikipediaКонфигурируется декларативно на XML-

языке POM (Project Object Model)Проект Maven ~= java-модуль“Соглашение превыше конфигурации”

Page 17: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Maven репозиторийМногие java-библиотеки публично

опубликованы как проекты MavenMaven Project ~= java-библиотека + POM-

файл + ресурсыПроекты доступны в центральном

репозитории Maven http://search.maven.org/

Page 18: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Maven проектыКаждый опубликованный maven-проект

имеет уникальный идентификаторИдентификатор состоит из имени группы,

имени артефакта, версии.Внутри проекта смежные артефакты

различаются т.н. классификатором

Page 19: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Пример проектаcom.google.guava:guava-gwt:17.0

Группа - com.google.guavaАртефакт - guava-gwtВерсия - 17.0Неявный классификатор - jar

Page 20: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Структура проекта/lection01 |-- src/ | |-- main/ | | |-- java/ | | | \-- ru/fizteh/java/fediq/ # Структура пэкейджа | | | \-- LectionMain.java | | \-- resources/ | | \-- config.properties | \-- test/ | \-- java/ | \-- ru/fizteh/java/fediq/ | \-- LectionTest.java \-- pom.xml # конфигурация проекта

Page 21: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Пример конфигурации Maven<project> <modelVersion>4.0.0</modelVersion> # Волшебство <groupId>ru.fizteh.java2.fediq</groupId> # Аналог package <artifactId>lection-maven</artifactId> # Имя проекта <version>1.0</version> # Версия <dependencies> <dependency> # Используемая библиотека <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>2.5.6</version> </dependency> </dependencies></project>

Page 22: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Конфигурация Maven

Page 23: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Жизненные циклы проекта MavenСборка состоит из этапов - жизненных циклов

(lifecycles)Циклы выполняются последовательно, с

первого до целевогоКраткий список жизненных циклов - verify,

compile, test, install, deployСборочная задача может быть присвоена

какому-то этапу или выполняться отдельно

Page 24: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Работа с Maven$ mvn dependency:tree # Показать дерево зависимостей$ mvn dependency:copy-dependencies # Скачать все зависимости

$ mvn compile # Скомпилировать код$ mvn test # Запустить юнит-тесты$ mvn package # Собрать (сжать и т.д.) артефакты$ mvn install # Загрузить артефакт в локальный репозиторий$ mvn deploy # Загрузить артефакт в удаленный репозиторий$ mvn clean # Убрать за собой всякое

$ mvn clean install # Пересобрать проект

$ mvn install # = mvn validate compile test package install ...

Page 25: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

ЗависимостиЗависимости проекта перечисляются в

блоке <dependencies>Maven умеет отслеживать транзитивные

зависимостиВо время сборки maven автоматически

скачает все необходимые файлыЗадача dependencies:copy-dependencies

сложит зависимости в директорию target/

Page 26: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

ScopesScope - ситуация или этап, в котором

потребуется зависимостьprovided - только для компиляцииruntime - только в рантаймеtest - только в тестеcompile (default) - на стадии компиляции и в

рантаймеsystem - предоставляется окружением

Page 27: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Пример указания зависимостей<dependencies> <dependency> <groupId>com.jolbox</groupId> <artifactId>bonecp</artifactId> <version>0.8.0.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency></dependencies>

Page 28: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

ПлагиныЗадачи в maven поставляются плагинамиПлагин содержит в себе несколько целейПлагины содержатся в тех же

репозиториях, что и другие проектыПлагины также “достаются” автоматическиПлагин конфигурируется в pom-файлеРяд плагинов подключен по умолчанию -

clean, compile, install, surefire и др.

Page 29: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Пример конфигурации плагина<build> ... <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins></build>

Page 30: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Пример конфигурации плагина<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <skip>true</skip> <skip>false</skip> <testFailureIgnore>true</testFailureIgnore> </configuration></plugin>

Page 31: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Пример конфигурации плагина<plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>someone-execution-id</id> <phase>package</phase> <goals> <goal>attached</goal> </goals> </execution> </executions></plugin>

Page 32: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

JAR-файлыПо окончании сборки проект будет

упакован в jar-файлjar - это обычный zip-архив, содежащий

скомпилированные классы и метаданныеПри желании, в аналогичные jar-файлы

можно сохранить исходники, ресурсы и прНа последней стадии (деплое) jar-файлы

заливаются в репозиторий

Page 33: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Наследование проектовДля поддержки принципа DRY maven

поддерживает наследование проектовОсновная конфигурация производится в

“родительском” проектеДочерние проекты подключают его с

помощью тега <parent>Часто родительский проект является

корнем “многомодульного” проекта

Page 34: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Многомодульные проектыГруппа близких проектов может быть

объединена в многмодульный проектВсе модули перечисляются в корневом

проекте в теге <modules/>Также в корневом проекте указывается

<packaging>pom</packaging>

Page 35: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Пример - корневой проект<project> <modelVersion>4.0.0</modelVersion> <groupId>ru.fizteh.java2</groupId> <artifactId>parent-pom</artifactId> <packaging>pom</packaging> <version>1.0</version> <modules> <module>example-jdbc</module> <module>example-spring</module> </modules> <build/> ... <dependencies/> ...</project>

Page 36: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Пример - дочерний проект<project> <parent> <groupId>ru.fizteh.java2</groupId> <artifactId>parent-pom</artifactId> <version>1.0</version> </parent> <groupId/> <version/> … # Унаследованные параметры можно перезаписывать <artifactId>example-jdbc</artifactId> <packaging>jar</packaging>

<dependencies/> ...</project>

Page 37: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Рекомендуемая литература

Page 38: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Компоновка приложенияПромышленное программирование

Page 39: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Связанность кода

http://infomgmt.wordpress.com/

Page 40: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Больше кода - сложнее работатьСо временем число сущностей растетЧисло связей растет на порядок быстрееЕсли не предпринять мер, быстро

наступает коллапс разработки

Page 41: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

И это очень частая проблема

Page 42: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Финансовые аспектыСложность рефакторингаСложность изменения APIВремя вхождения (нового разработчика)Коэффициент автобуса

Page 43: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Логическая компонентаКомпонента - автономная логическая

единица кодаВнутри компоненты происходит

контролируемое тесное взаимодействиеНаружу предоставляется API (контракт)Компонента взаимодействует с соседями

через их API

Page 44: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Слабая связанность

http://infomgmt.wordpress.com/

Page 45: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Сильная связанность

http://infomgmt.wordpress.com/

Page 46: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Закон ДеметрыЕсли у A есть доступ к Би у Б есть доступ к В,то А не нужен доступ к В

Page 47: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Уровни связанностиСодержимоеОбщее состояниеВнешний контрактСтруктура данныхСообщенияНет связности

Page 48: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Связность (сцепление) компонентыКомпонента должна быть осмысленнаЕе части должны иметь что-то общееСвязность - мера взаимосвязи между

составными частями одной компонентыПринцип наименьшего удивления

опирается на связность

Page 49: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Типы связности (сцепления)ФункциональнаяПоследовательнаяВременная/процедурнаяЛогическая/тематическаяСлучайная

Page 50: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Фрактальная природа компонентыКомпонента создана на основе маленьких

составных частейИх разработчик рассматривал каждую

такую часть как отдельную компонентуВаша сложная система - на самом деле,

одна из компонент в бизнес-процессе

Page 51: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Фрактальная природа компоненты

Page 52: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Основная идея проектированияМеньше связанность - больше сцепление

Page 53: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

МодульностьМодульность - принцип разработки ПО,

согласно которому код разделяется на отдельные функционально законченные сущности - модули

Это позволяет переиспользовать кодЭто упрощает проектированиеЭто упрощает дистрибуцию (см. Maven)

Page 54: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

SPI - набор интерфейсов, предлагаемый к реализации пользователями

API - набор моделей, интерфейсов и т.п., реализованный модулем

Контракт - формальное соглашение об использовании модуля

Contract-first Development - парадигма разработки “от контракта”

SPI, API, контракт

Page 55: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Интерфейс и реализацияКак правило, API модуля не содержит

сложных конструкций и зависимостейВнешние интерфейсы (API) модуля можно

выделить в отдельный легкий модульРеализация остается в отдельном тяжелом

модуле, о котором пользователи могут не знать

Page 56: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Зависимости между модулямиПереизбыток зависимостей в системе

вызывает непредсказуемые проблемыРазделение реализации и интерфейса

сильно сокращает объем знаний и зависимостей, необходимый для использования модуля

Page 57: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Внедрение зависимостей

Page 58: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Пример прямого управленияvoid main() { Brain brain = new MonkeyBrain(); Tail tail = new FishTail(); TeethHolder teeth = new SharkJaws(); //Animal animal = new FourLimbedMonster(); FourLimbedMonster animal = new FourLimbedMonster(); animal.setTail(tail); animal.setTeethHolder(teeth); animal.doHunt(); // NoSuchBrainException}

Page 59: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Пример прямого управленияvoid main() { Brain brain = new MonkeyBrain(); Tail tail = new FishTail(); TeethHolder teeth = new SharkJaws(); Animal animal = new FourLimbedMonster(brain, tail, teeth); animal.doHunt();}

Page 60: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Встроим зависимостиinterface DependencyInjector { void put(Object o); <T> T get(Class<T> clazz);}

Page 61: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Встроим зависимостиclass FourLimbedMonster implements Animal { Brain brain; TeethHolder teeth; Tail tail;

public FourLimbedMonster(DependencyInjector di) { brain = di.get(Brain.class); teeth = di.get(TeethHolder.class); tail = di.get(Tail.class); }}

Page 62: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Встроим зависимостиvoid main() { DependencyInjector di = new DependencyInjectorImpl(); di.put(new MonkeyBrain()); di.put(new FishTail()); di.put(new SharkJaws()); Animal animal = new FourLimbedMonster(di); animal.doHunt();}

Page 63: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Выделим зависимости в модулиclass ModuleWithBodyParts { public static void fillBodyParts(DependencyInjector di) { di.put(new MonkeyBrain()); di.put(new FishTail()); di.put(new SharkJaws()); }}class ModuleWithAnimal { public static Animal buildAnimal(DependencyInjector di) { return new FourLimbedMonster(di); }}

Page 64: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Выделим зависимости в модулиvoid main() { DependencyInjector di = new DependencyInjectorImpl(); ModuleWithBodyParts.fillBodyParts(di); Animal animal = ModuleWithAnimal.buildAnimal(di); animal.doHunt();}

Page 65: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Обобщим еще немногоinterface DependenciesSource { void fill(DependencyInjector di);}

void main(List<DependenciesSource> sources) { DependencyInjector di = new DependencyInjectorImpl(); for (DependenciesSource source : sources) { source.fill(di); } di.get(Animal.class).doHunt();}

Page 66: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Spring FrameworkПромышленное программирование

Page 67: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Хочется Dependency Injection?

Page 68: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Spring FrameworkМощная инфраструктурная платформа для

создания сложного JVM-based ПОИнтеграция со множеством популярных

фреймворков, внешних сервисов и JSRСквозная концепция программированияОгромное сообществоДе-факто стандарт Java-платформы

Page 69: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Из коробки:Application Context - DI и каталог ресурсовИнтеграция с БД (JDBC, ORM, транзакции)Web - Servlets, MVC, JSP, REST, ...XML и JSON биндингиSpEL - язык для управления ресурсамиAOP, Instrumentation и прочий сатанизмТестирование с JUnit и TestNG...

Page 70: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Пример из жизниpublic interface Brain { String getIdea();}

public interface Animal { String doHunt();}

Page 71: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Пример из жизниpublic class MonkeyBrain implements Brain { public String getIdea() { return "Banana"; }}

Page 72: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Пример из жизниpublic class Kitten implements Animal { private Brain brain; public void setBrain(Brain brain) { this.brain = brain; } public String doHunt() { return String.format("Meow, %s!", brain.getIdea()); }}

Page 73: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Пример из жизниimport org.springframework.context.ApplicationContext;

void main() { ApplicationContext ctx = ...; // Magic

Animal animal = ctx.getBean(Animal.class);

animal.doHunt(); // Meow, Banana!}

Page 74: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

XML-based заклинания

Page 75: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Spring XML config<beans ... > <bean name="someoneBrain" class="MonkeyBrain"/>

<bean name="kitten" class="Kitten"> <property name="brain" ref="someoneBrain"/> </bean></beans>

Page 76: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Шапка выглядит так<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 ">

Page 77: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Autowiring<beans ... > <bean name="someoneBrain" class="MonkeyBrain"/>

<bean name="kitten" class="Kitten" autowire=”byType”/>

<bean name="kitten" class="Kitten"> <property name="brain" ref="someoneBrain"/> </bean></beans>

Page 78: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Autowiring by default<beans ... default-autowire="byType"> <bean name="someoneBrain" class="MonkeyBrain"/>

<bean name="kitten" class="Kitten"/></beans>

Page 79: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Запуск контекстаvoid main() { ApplicationContext ctx = new ClassPathXmlApplicationContext("ctx.xml");

Animal animal = ctx.getBean(Animal.class);

animal.doHunt(); // Meow, Banana!}

Page 80: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Annotation-based заклинания

Page 81: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

@Component annotation@Componentpublic class MonkeyBrain implements Brain { public String getIdea() { return "Banana"; }}

Page 82: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

@Autowired annotation@Componentpublic class Kitten implements Animal { @Autowired private Brain brain;

public String doHunt() { return String.format("Meow, %s!", brain.getIdea()); }}

Page 83: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Запуск контекстаvoid main() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.scan(“package.name”); ctx.refresh(); Animal animal = ctx.getBean(Animal.class); System.out.println(animal.doHunt());}

Animal animal = ctx.getBean(Animal.class);

animal.doHunt(); // Meow, Banana!}

Page 84: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

@Configuration и @ComponentScan@Configuration@ComponentScan("package.name")public class AnimalsConfig { @Bean public Brain fishBrain() { return new Brain() { public String getIdea() {return "Bobble";} }; }}

Page 85: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Запуск контекстаvoid main() { ApplicationContext ctx = new AnnotationConfigApplicationContext(AnimalsConfig.class);

Animal animal = ctx.getBean(Animal.class);

animal.doHunt(); // Meow, Bobble!}

Page 86: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Жизненный цикл контекста

Page 87: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Bean Lifecycle1.Расчитывается граф (DAG) зависимостей2.Инициализируются зависимости бина3.Выставляются ссылки на зависимости4.Запускаются инициализаторы5.Бин живет, контекст запущен6.Запускаются деструкторы7.Граф зависимостей уничтожается в

обратном порядке

Page 88: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

InitializingBean и DisposableBeaninterface InitializingBean { void afterPropertiesSet() throws Exception;}

interface DisposableBean { void destroy() throws Exception;}

Page 89: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Пример DisposableBeanclass ClosableOne impelements Closable, DisposableBean { @Overwrite public void close() throws IOException { … }

@Overwrite public void destroy() throws Exception { close(); }}

Page 90: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

@PostConstruct и @PreDestroyclass NamedOne implements Closable { @Autowired private String name; private String formattedName;

@PostConstruct public void init() {formattedName = format(name);}

@PreDestroy @Overwrite public void close() { … }}

Page 91: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Awaresinterface BeanNameAware { void setBeanName(String name) …;}

interface ResourceLoaderAware { void setResourceLoader(ResourceLoader loader) …;}

interface ApplicationContextAware { void setApplicationContext(ApplicationContext ctx) …;}

Page 92: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

@Lazy@Lazy@Serviceclass ReallyHardService {

@PostConstruct void veryLongInitializing() { … };

void almostUselessMethod() { … };}

Page 93: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Рекомендуемая литература

Page 94: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Maven dependencies<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.0.6.RELEASE</version></dependency>

<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.0.6.RELEASE</version> <scope>test</scope></dependency>

Page 95: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Окружение и запускПромышленное программирование

Page 96: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Ресурсы приложения

Page 97: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Как передать коэффициент в бин?class CalibratingOne { @Autowired // Any double?! double coefficient; @Autowired // Other any double?! double scale;}

Page 98: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

@Valueclass CalibratingOne { @Value(“${property.name}”) double coefficient; @Value(“${prop.scale:1.0}”) double scale; // здесь 1.0 - дефолтное значение}

Page 99: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

PropertiesPlaceholderConfigurer@Configuration@PropertySource(“classpath:application.properties”)class ApplicationConfiguration { @Bean public PropertiesPlaceholderConfigurer props() { return new PropertiesPlaceholderConfigurer(); }}

Page 100: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

.properties-файлыru.fizteh.java2.example3.coefficient=5.0ru.fizteh.java2.example3.scale=0.8

# comments allowedru.fizteh.java2.mysql.port=3306ru.fizteh.java2.mysql.user=fediqru.fizteh.java2.mysql.password=Very$tr0ngPa66w*rd

Page 101: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

System propertiesjava … \ -Dru.fizteh.app.mode=yarr \ -Dru.fizteh.app.count=133 \ … \ ru.fizteh.app.MainClass \ command line args

Page 102: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

@Resource@Serviceclass CheapCalculator implements BillCalculator { Bill calcCost(Order order) { return new Bill(order.getCosts()); }}@Serviceclass CostyCalculator implements BillCalculator { Bill calcCost(Order order) { return new Bill(order.getCosts() * 2); }}

Page 103: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

@Resourceclass OrderProcessor { @Autowired // which one? BillCalculator billCalculator;

public BigDecimal processOrder(Order order) { return billCalculator.calcCost(order).getPrice(); }}

Page 104: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

@Resourceclass OrderProcessor { @Resource(name = “cheapCalculator”) BillCalculator billCalculator;

public BigDecimal processOrder(Order order) { return billCalculator.calcCost(order).getPrice(); }}

Page 105: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

@Resource@Service // = @Service(“cheapCalculator”) // Default nameclass CheapCalculator implements BillCalculator { Bill calcCost(Order order) { return new Bill(order.getCosts()); }}@Service(“ohohoCalculator”) // Custom nameclass CostyCalculator implements BillCalculator { Bill calcCost(Order order) { return new Bill(order.getCosts() * 2); }}

class OrderProcessor { @Autowired BillCalculator billCalculator; public BigDecimal processOrder(Order order) { return billCalculator.calcCost(order).getPrice(); }}

Page 106: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Взятие бинов из контекстаclass Cook { @Autowired // like ApplicationContextAware ApplicationContext ctx;

public void cook() { Pan pan = ctx.getBean(Pan.class) Map<String, Food> namedFood = ctx.getBeansOfType(Food.class); Food fish = ctx.getBean(“fish”, Food.class); }}

Page 107: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Взятие параметров из контекстаclass Accountant{ @Autowired // like ApplicationContextAware ApplicationContext ctx;

public void report() { Environment env = ctx.getEnvironment(); String cardHolder = env.getProperty(“cardHolder”); double tax = env.getPropertyAsClass(“tax”, Double.class) }}

Page 108: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Взятие файлов из контекстаclass Reader { @Autowired // like ResourceLoaderAware ResourceLoader loader; // вообще-то, это тот же контекст

public void read() { Resource resource = loader.getResource(“file.txt”); URI uri = resource.getURI(); String body = IOUtils.toString( // apache commons-io resource.getInputStream()); }}

Page 109: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Non-required wiringclass Logger { @Autowired(required = false) Printer printer;

public void log(String s) { if (printer != null) { printer.print(s); } … }}

Page 110: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

SLF4J + Log4J

Page 111: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Использование логгераimport org.slf4j.Logger;import org.slf4j.LoggerFactory;

class SomeoneActor { private static final Logger log = LoggerFactory.getLogger(SomeoneActor.class);

void doSomething(Object event) { log.warn(“Oh, god, {} happens!”, event); }}

Page 112: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Использование логгераvoid doSomethingWrong(String arg) { try { doSomethingBad(arg); } catch (AnyException e) { log.error(“Bad with {} happens”, arg, e) // Если последний аргумент - исключение, // то в лог будет выведен stack trace }}

Page 113: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Уровни логгингаtrace - “шаг левой… шаг правой…”debug - “идем прямо… все еще идем...”info - “надо идти прямо 32 км”warn - “пришлось обойти лужу”error - “потерял карту, упал в яму, промок”fatal - (в SLF4J нет) “сломал обе ноги,

прощай, жестокий мир”

Page 114: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Maven Dependencies<!-- SLF4J core API --!><dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.7</version></dependency>

<!-- SLF4J to Log4J bridge --!><dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.7</version></dependency>

<!-- Log4J implementation --!><dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version></dependency>

Page 115: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

log4j.xml<log4j:configuration> <appender .../> <category .../> <root .../></log4j:configuration>

Page 116: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

log4j.xml header<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"><log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

Page 117: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

log4j.xml category<category name="ru.fizteh"> <priority value="ALL"/> <!-- Most important --!></category>

<category name="wire"> <priority value="NONE"/> <!-- NO U!!! --!></category>

<category name="org.springframework"> <priority value="WARN"/> <!-- Don’t worry --!></category>

Page 118: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

log4j.xml appender<appender name="console" class="org.apache.log4j.ConsoleAppender">

<param name="Target" value="System.out"/>

<layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value= "%-d{ISO8601} [%15.15t] %-5p %30.30c - %m%n"/> </layout>

</appender>

Page 119: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Conversion Pattern explained%d{ISO8601} - дата в формате ISO-8601%p - приоритет (уровень логгинга)%t - thread, имя потока%c - имя логгера (имя класса)%с{1} - последнее слово в имени логгера%m - логируемое сообщение%n - перевод строки

Page 120: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Conversion Pattern explainedprintf-like formattingДо точки - минимальное число знаковПосле точки - максимальное число знаковС минусом - слева направоБез минуса - справа налево%-10.20c = поле от 10 до 20 символов,

заполнять слева направо, имя класса

Page 121: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

log4j.xml root<root> <!-- Прочие категории интересуют нас от INFO и выше --> <priority value="INFO"/> <!-- Льем все в console --> <appender-ref ref="console"/></root>

Page 122: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

%-d{ISO8601} [%t] %-5p %20.20c %m%n2014-09-14 00:47:42,912 [main] INFO .java2.ServerStarter Starting web server2014-09-14 00:47:42,913 [main] DEBUG eh.java2.util.Reader Reading config.xml2014-09-14 00:47:42,913 [main] DEBUG eh.java2.util.Reader Reading pages.xml2014-09-14 00:47:42,913 [main] WARN eh.java2.util.Reader Cannot read trololo.xml2014-09-14 00:47:42,914 [main] ERROR .java2.ServerStarter Failed to open socketjava.net.BindException: Permission denied

at java.net.PlainSocketImpl.socketBind(Native Method)at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:382)at java.net.ServerSocket.bind(ServerSocket.java:375)at java.net.ServerSocket.<init>(ServerSocket.java:237)at java.net.ServerSocket.<init>(ServerSocket.java:128)at ru.fizteh.java2.ServerStarter.openSocket(ServerStarter.java:30)at ru.fizteh.java2.ServerStarter.main(ServerStarter.java:23)

Page 123: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Боевой запуск приложения

Page 124: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Что нужно сделать для запуска?Допустим, компиляция уже завершена

Собрать библиотеки зависимостей, собственные классы и файлы ресурсов

Построить из них classpathЗапустить JVM* с нужными аргументамиИногда вместо отдельной JVM можно

запустить приложение в общем контейнере

Page 125: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Запуск через Shell-скрипт#!/bin/sh

mvn clean packagemvn dependency:copy-dependencies

CLASSPATH=$(find target/ -name "*.jar" -printf "%f:")

java -cp $CLASSPATH \ -Dhard.coded.args=fixed.values \ -ru.fizteh.java2.MainClass "$@"

Page 126: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Упаковка в Web App Archive (.war)# Нужны правки в pom.xml, смотрите их в следующих серияхmvn clean compile war:war

# Копируем war-файл в Application Servercopy target/myapp.war $TOMCAT_HOME/webapps/# При должной настройке приложение запустится само# Подробнее о веб-приложениях в следующих сериях

chrome http://localhost:8080/myapp

Page 127: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Spring BootНабор библиотек, бесстыдно облегчающий

запуск Spring-based приложенийАвтоматически конфигурирует Spring,

manifest.mf, Application Server, etc…Тесно интегрирован с Maven и Gradle

Page 128: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Spring Boot Maven Plugin<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>1.1.6.RELEASE</version> <executions> <execution> <goals><goal>repackage</goal></goals> </execution> </executions></plugin>

Page 129: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Spring Boot в коде@Configuration@EnableAutoConfiguration // Опциональноclass AppConfig { ... public static void main(String[] args) { SpringApplication.run(AppConfig.class); }}

Page 130: Industrial Programming Java - Lection Pack 01 - Building an application - Lavrentyev Fedor

Запуск с помощью Spring Bootmvn clean package # если в конфиге указан goal repackagemvn clean package spring-boot:repackage # если не указан

# запуск прямо из mavenmvn spring-boot:run

# В repackaged jar упакованы зависимости и настроен main class# Его можно распространять отдельно и запускать напрямуюjava -jar target/app.jar