Skip to content

Latest commit

 

History

History

Spring_part_4

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Spring (Core) lessons part 4 - Java-based Configuration.

В папке DOC sql-скрипты и др. полезные файлы.

Док. для изучения:

  • Spring Framework 3.2.x Reference Documentation ;
  • Spring Framework 6.1.5 Documentation ;
  • Пакет org.springframework.context.annotation - Поддержка аннотаций для контекста приложения, включая «общие» аннотации JSR-250, сканирование компонентов и метаданные на основе Java для создания объектов, управляемых Spring;
  • Пакет org.springframework.stereotype - Аннотации, обозначающие роли типов или методов в общей архитектуре (на концептуальном, а не на уровне реализации); Предназначен для использования инструментами и аспектами (идеальная target для pointcut);
  • Пакет org.springframework.beans.factory - Базовый пакет, реализующий облегченный контейнер Spring Inversion of Control (IoC); Предоставляет альтернативу шаблонам проектирования Singleton и Prototype, включая согласованный подход к управлению конфигурацией. Создан на основе пакета org.springframework.beans;
  • Пакет org.springframework.context - Этот пакет основан на пакете bean-компонентов и добавляет поддержку источников сообщений и шаблона проектирования Observer, а также возможность объектам приложения получать ресурсы с использованием согласованного API; Приложениям Spring нет необходимости явно зависеть от ApplicationContext или даже от функциональности BeanFactory. Одной из сильных сторон архитектуры Spring является то, что объекты приложений часто можно настраивать без какой-либо зависимости от API-интерфейсов Spring;
  • Пакет org.springframework.core.env - Абстракция среды (окружения) Spring, состоящая из профиля определения компонента и поддержки иерархического источника свойств;

!!! При чтении учебного кода рекомендуется внимательно изучать комментарии к оному и запускать приложение в режиме DEBUG для более эффективного наблюдения за процессами происходящими в приложении !!!


Для начала проведем предварительную подготовку:

Шаг 1. - в файле build.gradle добавим необходимые нам зависимости:

/* Подключим Spring-core и Spring-context. */
implementation 'org.springframework:spring-core:5.3.22'
implementation 'org.springframework:spring-context:5.3.22'

Шаг 2. - подключаем Jakarta Annotation API:

implementation 'jakarta.annotation:jakarta.annotation-api:1.3.5'

Шаг 3. - для того, чтобы обрабатывать аннотации, мы добавляем в application.xml нужные строки и удаляем все лишнее (указываем Sprig-у какую папку сканировать на наличие аннотаций @Component, @Controller, @Repository, @Service:

<context:component-scan base-package="spring.oldboy"/> 

В Spring lessons (part 1 - part 2 - part 3) мы настраивали bean-компоненты Spring с помощью файла конфигурации *.XML (см. resources/application.xml) и немного при помощи аннотаций. Теперь приступим к настройке наших bean-ов на основе Java конфигурирования.

Конфигурация на основе Java позволяет настроить работу Spring приложения без использования *.XML, а с помощью нескольких аннотаций на основе Java.


Аннотация класса с помощью @Configuration указывает, что класс может использоваться контейнером Spring IoC в качестве источника определений bean-компонентов. Аннотация @Bean сообщает Spring-у, что метод, помеченный @Bean, вернет объект, который должен быть зарегистрирован как bean-компонент в контексте приложения Spring-а. Самый простой возможный класс @Configuration будет следующим:

package spring.oldboy;
import org.springframework.context.annotation.*;

@Configuration
public class HelloWorldConfig {
    @Bean
    public HelloWorld helloWorld(){
        return new HelloWorld();
    }
}

Приведенный выше код будет эквивалентен следующей конфигурации *.XML:

<beans>
   <bean id = "helloWorld" class = "spring.oldboy.HelloWorld" />
</beans>

В данном примере - имя метода помечено @Bean, и работает как идентификатор компонента, создает и возвращает фактический компонент. Наш класс конфигурации может иметь объявление более чем для одного @Bean-а. После того как наши классы конфигурации определены, мы можем загрузить и предоставить их в контейнер Spring с помощью AnnotationConfigApplicationContext:

public static void main(String[] args) {
    ApplicationContext appContext = 
                    new AnnotationConfigApplicationContext(HelloWorldConfig.class);

    HelloWorld helloWorld = appContext.getBean(HelloWorld.class);
    
    helloWorld.setMessage("Hello World!");
    helloWorld.getMessage();
}

Мы можем загрузить различные классы конфигураций следующим образом:

public static void main(String[] args) {
    AnnotationConfigApplicationContext appContext = 
                            new AnnotationConfigApplicationContext();

    appContext.register(AppConfig.class, OtherConfig.class);
    appContext.register(AdditionalConfig.class);
    appContext.refresh();
}

Доп. док. для изучения:


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

Когда @Bean-ы имеют зависимости друг от друга, выразить эту зависимость просто:

package spring.oldboy;
import org.springframework.context.annotation.*;

@Configuration
public class AppConfig {
    @Bean
    public Foo foo() {
        return new Foo(bar());
    }
    @Bean
    public Bar bar() {
        return new Bar();
    }
}

Здесь компонент foo получает ссылку на bar через внедрение в конструктор.

Доп. док. для изучения:


Lesson 19 - @Configuration

Создадим папку для хранения всех наших конфигураций - config.

Фактически для работы Spring приложения, обычно используют несколько файлов конфигураций, для логического разделения функциональности:

  • управление БД;
  • управление web-частью приложения (Web Services, Web Flow, Session и т.д.);
  • управление работой message broker (integration broker, interface engine) (ActiveMQ, Kafka, Qpid, RabbitMQ);
  • общий конфигурационный файл, для управления всем набором конфигураторов;

В папке config создаем ApplicationConfiguration.java и аннотируем его @Configuration. Далее перетащим в него из application.xml максимально возможный набор управляющих конфигурацией настроек.

Погнали!

  1. Аннотация @PropertySource является повторяемой, т.е. сама аннотирована как @Repeatable, что означает для нас возможность размещать ее над аннотируемыми классами по нескольку штук и указывать необходимые пути к файлам настроек.

Из файла application.xml стока с указанием пути к файлу свойств:

<context:property-placeholder location="classpath:application.properties"/>

Превращается в аннотацию в файле ApplicationConfiguration.java:

@PropertySource("classpath:application.properties")

На данном этапе наш JavaConfigAndXmlDemo.java все еще работает и выдает результат.

  1. Аннотация @ComponentScan над ApplicationConfiguration и ее параметры, практически полностью повторяют настройки из application.xml:

    <context:component-scan base-package="spring.oldboy" annotation-config="true" resource-pattern="**/*.class" scoped-proxy="no" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/> <context:include-filter type="assignable" expression="spring.oldboy.repository.CrudRepository"/> <context:include-filter type="regex" expression="spring.oldboy..+Repository"/> </context:component-scan>

И выглядят как:

@ComponentScan(basePackages = "spring.oldboy",
                        useDefaultFilters = false,
    includeFilters = {
                @Filter(type = FilterType.ANNOTATION, value = Component.class),
                @Filter(type = FilterType.ASSIGNABLE_TYPE, value = CrudRepository.class),
                @Filter(type = FilterType.REGEX, pattern = "com\\..+Repository")
})

На данном этапе в IoC контейнере находятся bean-ы созданные согласно нашей Java-конфигурации и OnlyJavaConfigDemo.java прекрасно это демонстрирует. Мы не видим часть bean-ов которые создавали ранее используя application.xml.


Lesson 20 - @ImportResource и @Import

Spring предоставляет аннотацию @ImportResource, которая используется для загрузки bean-компонентов из файла applicationContext.xml в контекст приложения. Применительно к нашему ApplicationConfiguration.java мы получаем комбинированный способ создания 'контекста' используя и XML конфигурирование (Groovy скрипты) и аннотации и Java настройку будущего Spring приложения.

Аннотация @Import позволяет группировать классы конфигураций (например):

@Configuration
@Import({ DogConfig.class, CatConfig.class })
class MammalConfiguration {
}

См. наш ApplicationConfiguration.java


Lesson 21 - @Bean

@Bean - это аннотация уровня метода и прямой аналог элемента XML . Аннотация поддерживает большинство атрибутов, предлагаемых , например: init-method, destroy-method, autowiring, lazy-init, dependency-check, depends-on and scope.

Объявление bean - компонента происходит через добавление аннотации @Bean к методу. Когда JavaConfig обнаруживает такой метод, он выполнит этот метод и зарегистрирует возвращаемое значение как компонент внутри BeanFactory реализации. По умолчанию имя компонента будет таким же, как имя метода. Ниже приведен простой пример объявления @Bean метода:

@Configuration
public class AppConfig {
    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl();
    }
}

Для сравнения, приведенная выше конфигурация в точности эквивалентна следующему Spring XML:

<beans>
    <bean name="transferService" class="com.acme.TransferServiceImpl"/>
</beans>

Оба варианта приведут к тому, что bean-компонент с именем transferService будет доступен в BeanFactory / ApplicationContext и привязан к экземпляру объекта типа TransferServiceImpl.

Внедрение зависимостей тоже упрощается. Когда @Bean-ы имеют зависимости друг от друга, выразить эту зависимость так же просто, как вызвать один метод компонента другим:

@Configuration
public  class AppConfig {
    @Bean 
    public Foo foo() {
        return new Foo(bar());
    }
    @Bean 
    public Bar bar() {
        return new Bar();
    }
}
  • ApplicationConfiguration.java - пример файла конфигурации, в котором созданы bean используя аннотацию @Bean
  • BeanJavaConfigDemo.java - простая демонстрация работоспособности контекста на основе Java конфигурации.

Lesson 22 - @Profile

Профили Spring предоставляют возможность разделить части конфигурации нашего приложения и сделать их доступными только в определенных средах. Любой @Component или @Configuration может быть помечен значком @Profile для ограничения при загрузке:

@Configuration
@Profile("production")
public class ProductionConfiguration {
        // some code ...
}

В обычном случае в Spring мы можем использовать spring.profiles.active Environment свойство, чтобы указать, какие профили активны. Мы можем указать свойство любым из обычных способов, например, мы можем включить его в свой application.properties:

spring.profiles.active=dev,hsqldb

или указать в командной строке с помощью переключателя: --spring.profiles.active=dev,hsqldb.

  • application.properties - в последней строке приведен пример профилирования, и следовательно, активации того или иного профиля через файл свойств.

Мы также можем программно установить активные профили, вызвав их SpringApplication.setAdditionalProfiles(...) перед запуском приложения. Также можно активировать профили с помощью ConfigurableEnvironment интерфейса Spring.

Поскольку в BeanDefinitionNamesDemo мы прописали только один профиль:

myContext.getEnvironment().setActiveProfiles("prod");

А в файле application.properties задан только: spring.profiles.active=production, то в результирующем списке bean-в мы не найдем: spring.web_demo_config.WebConfiguration