Содержание
Интерфейс ApplicationContext
Интерфейс org.springframework.context.ApplicationContext
описывает основной функционал управляющего компонентами приложения контейнера Спринг. Именно имплементации этого класса создают, настраивают и внедряют друг в друга компоненты приложения, так называемые бины (Spring bean).
Параметры создания бинов и граф их зависимостей представляет собой так называемые конфигурационные метаданные (configuration metadata), ну, или просто конфигурацию приложения. Эта конфигурация должны описать какой компонент (бин) с какими параметрами создаётся, какие компоненты в какие внедряются в качестве зависимостей. Следуя описанной конфигурации контейнер во время старта приложения создаст все эти компоненты и свяжет их друг с другом, предоставив нам полностью готовое и сконфигурированное приложение.
Способы конфигурации Spring приложения
Существует несколько довольно разных способов передать Спрингу конфигурационные метаданные, то есть сообщить ему, какие бины нужно создать, как их инициализировать и как их внедрить друг в друга.
Например, нам нужно сообщить всем компонентам приложения, которые взаимодействуют с базой данных, по какому URL'у эта БД вообще доступна. Значит нам надо передать (пролить) строку вроде
jdbc:postgresql://localhost/test?user=fred&password=secret&ssl=true
в приложение. Эта строка – это и есть простейший параметр конфигурации приложения. И передать приложению этот параметр мы сможем одним из следующих способов:
- Поместив его в конфигурацию, описанную с помощью Java кода;
- Поместив его в конфигурацию, описанную в XML файле;
- Поместив его в конфигурацию, описанную в groovy файле.
Спринг позволяет использовать одновременно несколько различных способов описания конфигурации. Все настройки будут вычитаны и применены к приложению, как если бы они были описаны единообразно.
Конфигурация в виде Java кода
Самым распространённым на сегодняшний день способом передать Спрингу сведения о том, как нужно сконфигурировать компонент – это использование непосредственно java кода. Здесь сеть два подхода:
Первый называется Конфигурацией с помощью аннотаций (Annotation-based configuration) и заключается в том, что классы, объекты которых должны быть сконфигурированы как программные компоненты, управляемые контейнером, помечаются специальными аннотациями. При старте приложения Спринг вычитывает эти аннотации и в соответствии с ними как-то поступает с данным классом, например, инициализирует его объект и внедряет в качестве зависимости в другие объекты.
@Component public class DatabaseInitiaizer { private List < User > listOfUsers = new ArrayList < > (); @PostConstruct public void init() { User user = new User(1, "User"); ......
Второй называется Конфигурацией с помощью джавы (Java-based configuration) и заключается в том, что пишутся специальные конфигурационные классы, методы которых возвращают должным образом сконфигурированные бины. При таком подходе разработчик сам внутри этого метода создаёт объекты-экземпляры программных компонентов с помощью new
либо фабричных методов. Однако и здесь Спринг даёт возможность легко получить доступ к любым необходимым зависимостям без необходимости инстанциировать эти зависимости вручную.
@Configuration public class Config { @Bean public Connection mySQLConnection() { return new MySQLConnection(); } @Bean public Connection oracleConnection() { return new OracleConnection(); } }
Поскольку первый подход (обложить класс надлежащими аннотациями) предполагает доступ разработчика к исходному коду компонента, то он, как правило, чаще всего применяется к компонентам, разрабатываемым авторами данного приложения. Второй подход не требует доступа к исходникам и позволяет сделать бином абсолютно любой библиотечный компонент (хоть произвольную строку, что-угодно, что может быть объектом).
Так, если нам нужен в качестве бина, внедряемого в наши компоненты, например, http-клиент, на не нужно писать свой клиент или оборачивать библиотечный. Мы можем объявить объект класса java.net.http.HttpClient
бином с помощью второго подхода Спринг внедрит его во все компоненты, где он требуется.
Обратим внимание, что конфигурация с помощью джавы не обязательно должна лежать в одном классе, в одном файле. Обычно какие-то однотипные бины конфигурируют в одном классе, какие-то другие в других классах.
Конфигурация с помощью XML
Перечислить классы, которые должны быть бинами и управляться контейнером, можно в специальном xml-файле примерно следующего вида:
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- services --> <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 for services go here --> </beans>
Описания бинов, их взаимозависимости располагаются в одном или нескольких xml- файлов. Есть различные способы указать Спрингу из каких файлов вычитывать конфигурации и он будет их обрабатывать, как если бы они были в одном файле.
Конфигурация с помощью groovy файлов
Конфигурация приложения и его компонентов может быть описана в groovy файлах. Groovy, будучи функциональным языком программирования, очень хорошо подходит для написания кода в декларативном стиле, что в свою очередь делает его очень удобным для описания различных конфигураций. Однако, по каким-то причинам такой подход к описанию конфигурации Spring Приложений не прижился.
Выглядит конфигурация, описанная с помощью groovy следующим образом:
beans { dataSource(BasicDataSource) { driverClassName = "org.hsqldb.jdbcDriver" url = "jdbc:hsqldb:mem:grailsDB" username = "sa" password = "" settings = [mynew:"setting"] } sessionFactory(SessionFactory) { dataSource = dataSource } myService(MyService) { nestedBean = { AnotherBean bean -> dataSource = dataSource } } }