Java for Beginner
695 subscribers
603 photos
165 videos
12 files
932 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Подробный разбор решения задачи Task181024_2

Создание контекста: При инициализации ApplicationContext с помощью AnnotationConfigApplicationContext(AppConfig.class) Spring загружает конфигурационный класс AppConfig и создает все объявленные бины.

Создание MyService: Метод myService() в AppConfig создает и возвращает один экземпляр MyService (по умолчанию область действия — singleton). То есть, service1 и service2 указывают на тот же экземпляр MyService, поэтому выражение service1 == service2 выводит true.

Создание Dependency: В методе myService() вызывается метод dependency(), помеченный как
@Scope("prototype"), что означает создание нового объекта Dependency каждый раз при его вызове. Поэтому даже если MyService один и тот же, каждый его экземпляр использует свой объект Dependency.

Вывод:

service1 == service2 — true (оба указывают на один и тот же экземпляр MyService).
Метод getDependencyMessage() у service1 выводит строку "Injected Dependency Message".


#Solution_TasksSpring
👍2
Подробный разбор решения задачи Task211024_2

1. Создание контекста:

Программа начинается с создания контекста Spring при помощи AnnotationConfigApplicationContext, который принимает конфигурационный класс AppConfigTask. Это запускает процесс сканирования компонентов (аннотированных классов) и создает все нужные бины для работы приложения.

2. Конфигурационный класс AppConfigTask:


Класс AppConfigTask помечен аннотацией
@Configuration, что говорит Spring о том, что этот класс содержит определения бинов или конфигурацию для приложения.
Аннотация
@ComponentScan() указывает, что Spring должен сканировать текущий пакет по умолчанию на наличие компонентов с аннотацией @Component и создавать для них бины.

3. Класс MyServiceTest:


Класс помечен аннотацией
@Component, поэтому Spring создаст бин для этого класса.
В конструкторе MyServiceTest происходит автоматическая инъекция зависимости через параметр MyRepository myRepository, что значит, что Spring найдет бин типа MyRepository и передаст его в конструктор.
Также в конструкторе используется аннотация
@Value("CustomPrefix"), которая указывает Spring на необходимость подставить строку "CustomPrefix" в поле prefix. Это статическое значение, жестко заданное в коде, а не загружаемое из файла конфигурации.

4. Класс MyRepository:


Этот класс также помечен аннотацией
@Component, поэтому Spring создает его бин.
Метод getData() возвращает строку "Repository Data".

5. Работа программы:


После создания контекста в методе main происходит получение бина MyServiceTest через вызов context.getBean(MyService.class).
Затем вызывается метод printMessage() у объекта MyServiceTest
Внутри метода printMessage() выводится в консоль значение переменной prefix и результат вызова метода getData() у объекта myRepository. Значение переменной prefix задается через аннотацию
@Value и равно "CustomPrefix". Метод getData() возвращает строку "Repository Data".
Соответственно, в консоли будет выведена строка "CustomPrefix: Repository Data".

Почему это работает?


Spring находит классы MyServiceTest и MyRepository благодаря аннотации
@Component и создает для них бины.
Зависимость MyRepository инъектируется в MyServiceTest через конструктор, благодаря автоматической инъекции.
Аннотация
@Value("CustomPrefix") указывает на строку, которая напрямую передается в переменную prefix, обеспечивая статическое значение без необходимости внешнего конфигурационного файла.
Результат выводится с правильным форматом: значение из prefix и значение из метода getData().


#Solution_TasksSpring
Подробный разбор решения задачи Task221024_2

Задача состоит из трех ключевых компонентов:

Класс MyBean — бин, который Spring будет управлять.
Конфигурационный класс AppConfig221024 — используется для указания, что Spring должен искать компоненты (бины) в определенном пакете с помощью аннотации
@ComponentScan.
Метод main() — точка входа в программу, где создается Spring-контекст и управляется жизненным циклом бина.


Ключевые элементы задачи

Создание бина — через вызов конструктора.
Инициализация бина — через вызов метода afterPropertiesSet() из интерфейса InitializingBean.
Использование бина — через вызов метода doSomething() для выполнения основной логики.
Очистка и уничтожение бина — через вызов метода destroy() из интерфейса DisposableBean.


Детали работы программы

Класс MyBean:
Этот класс представляет собой обычный Spring-бин. Он отмечен аннотацией @Component, что позволяет Spring автоматически обнаруживать его при сканировании пакета.

Бин реализует два интерфейса:
InitializingBean (с методом afterPropertiesSet()), который вызывается после того, как Spring завершит инъекцию зависимостей и бин будет готов к использованию.
DisposableBean (с методом destroy()), который вызывается перед уничтожением бина, когда Spring-контекст закрывается.


Метод main():
Здесь создается Spring-контекст с использованием AnnotationConfigApplicationContext и передается класс конфигурации AppConfig221024.
После этого Spring автоматически находит бин MyBean, создает его экземпляр, инициализирует его, и предоставляет для использования в коде.
После завершения работы программы вызывается метод context.close(), который закрывает Spring-контекст, что вызывает метод очистки у бина.


Ход выполнения программы

Spring создает бин MyBean:
Когда Spring начинает работу, он находит класс MyBean, отмеченный аннотацией @Component, и создает его экземпляр.
При этом вызывается конструктор класса MyBean, который выводит в консоль строку "Constructor called".


Инициализация бина:
После создания экземпляра и завершения инъекции всех зависимостей, Spring вызывает метод afterPropertiesSet() из интерфейса InitializingBean.
Этот метод используется для выполнения задач, которые должны быть выполнены сразу после создания объекта (например, инициализация сложных зависимостей, проверка состояний и т.д.).
В нашем случае, этот метод выводит строку "afterPropertiesSet (init) called" в консоль.


Основная логика программы:
В методе main() вызывается метод doSomething() у бина. Этот метод выполняет некоторую основную логику программы и выводит строку "Doing something".

Закрытие контекста и разрушение бина:
Когда выполнение программы заканчивается, вызывается метод context.close(), который закрывает Spring-контекст. Это действие инициирует вызов метода destroy() из интерфейса DisposableBean, где бин должен освободить ресурсы или выполнить задачи очистки перед уничтожением.
В данном случае, метод destroy() выводит строку "destroy (cleanup) called".


Лог выполнения программы:
Сначала выводится "Constructor called" — бин создается, и вызывается его конструктор.
Затем выводится "afterPropertiesSet (init) called" — это метод инициализации, который вызывается после создания бина.
Далее выводится "Doing something" — это основная логика программы, выполняемая в методе doSomething().
Наконец, выводится "destroy (cleanup) called" — это метод разрушения бина, который вызывается при закрытии Spring-контекста.


#Solution_TasksSpring
👍1
Подробный разбор решения задачи Task231024_2

В этой задаче мы изучаем различия между синглтон (singleton) и прототип (prototype) бинами в контексте Spring Framework. Важно понять, как Spring управляет объектами с разными жизненными циклами (scopes) и сколько экземпляров класса создается в зависимости от области действия бина.

1. Конфигурация бинов

Класс Config содержит два бина:
singletonBean() возвращает объект класса MyBean2310 с областью действия singleton.
prototypeBean() возвращает объект того же класса, но с областью действия prototype.


Ключевые аннотации:
@Configuration: указывает на класс, содержащий определение бинов.
@Bean: создает и управляет объектом бина.
@Scope: указывает на область действия бина — singleton или prototype.

2. Класс MyBean2310

В конструкторе этого класса есть строковый параметр scope, который показывает, для какого типа области действия (singleton или prototype) создается объект. При создании объекта этот параметр передается, и выводится сообщение "MyBean created for <scope>".

3. Main-класс

Основной класс программы создает AnnotationConfigApplicationContext, который служит контейнером для Spring-менеджера бинов.

Здесь выполняются следующие действия:

Запрашивается бин singletonBean дважды: оба раза возвращается один и тот же экземпляр.
Запрашивается бин prototypeBean дважды: каждый раз создается новый экземпляр.


4. Ожидаемое поведение

Синглтон-область действия (singleton scope):
Spring создает только один экземпляр бина с областью действия singleton, и этот объект используется во всех запросах к контейнеру.
Вызовы getBean("singletonBean") возвращают один и тот же объект.


Прототип-область действия (prototype scope):
Каждый вызов getBean("prototypeBean") создает новый экземпляр бина, то есть при каждом запросе контейнер создает новый объект.

Пояснение вывода в консоль:
Первая строка выводится при первом вызове context.getBean("singletonBean"). Поскольку бин имеет область синглтон, этот же объект будет возвращаться при каждом последующем запросе, и повторного создания объекта не произойдет.
Вторая строка появляется при первом вызове context.getBean("prototypeBean"), где создается новый экземпляр прототипа.
Третья строка появляется при втором вызове context.getBean("prototypeBean"), где создается еще один новый экземпляр для прототипа.


Основные выводы:
Синглтон-бин создается один раз при первом запросе, и тот же экземпляр используется во всех последующих вызовах.
Прототип-бин создается каждый раз при запросе контейнера, то есть каждый вызов getBean() создает новый объект.


#Solution_TasksSpring
👍2
Подробный разбор решения задачи Task241024_2

В этой задаче исследуются различия между внедрением зависимостей через конструктор и через сеттер в Spring Framework. Рассмотрим поведение бинов, определённых в конфигурации Spring.

1. Конфигурация бинов

Класс Config2410 содержит два бина:
setterInjectedBean2410() создаёт бин MyBean2410 с использованием сеттер-инъекции.
constructorInjectedBean2410() создаёт бин MyBean2410 с использованием конструкторной инъекции.


Аннотации:
@Configuration: Указывает на класс, содержащий конфигурацию Spring и бинов.
@Bean: Создаёт объект бина и регистрирует его в контексте Spring.

2. Класс MyBean2410

Конструктор с параметром инжектирует зависимость через конструктор и выводит строку "Constructor injection".
Пустой конструктор выводит "No-arg constructor".
Метод setMyService2410() инжектирует зависимость через сеттер и выводит "Setter injection".
Метод useService2410() вызывает метод serve() объекта MyService2410, который выводит "Service called".


3. Класс Task241024_2

В основном классе программы создаётся AnnotationConfigApplicationContext, служащий контейнером для Spring-бинов.

Далее:

Вызывается бин setterInjectedBean2410 и создаётся экземпляр с помощью сеттера, сначала вызывается конструктор без параметров, затем вызывается сеттер для внедрения зависимости.
Вызывается бин constructorInjectedBean2410, и зависимость внедряется через конструктор.


Ожидаемый вывод:
При создании бина через сеттер вызывается конструктор по умолчанию, затем сеттер, что даёт вывод:
"No-arg constructor"
"Setter injection"
При создании бина через конструктор сразу вызывается конструктор с параметром:
"Constructor injection"
Оба бина вызывают метод useService2410(), который выводит:
"Service called"
"Service called"


Основные моменты:

Сеттер-инъекция требует двух этапов: вызов конструктора без параметров и затем вызов метода сеттера.
Конструкторная инъекция внедряет зависимость сразу при создании объекта.


#Solution_TasksSpring
👍2
Подробный разбор решения задачи Task251024_2

В этой задаче мы исследуем механизм внедрения зависимостей в Spring с использованием аннотаций @Autowired и @Qualifier. Эти аннотации используются для точного указания, какой бин должен быть внедрен, когда в контексте существует несколько бинов одного типа.

1. Конфигурация бинов

Класс Config2510 определяет два бина, реализующих интерфейс Service2510:
serviceA() возвращает экземпляр класса ServiceA2510, который выводит "Service A executed".
serviceB() возвращает экземпляр класса ServiceB2510, который выводит "Service B executed".
Здесь мы сталкиваемся с ситуацией, когда есть два бина одного типа (оба реализуют интерфейс Service2510), что требует от нас использования механизма разрешения неоднозначности.


2. Аннотации @Autowired и @Qualifier

Аннотация @Autowired указывает Spring, что этот конструктор должен быть использован для внедрения зависимости в Client2510. Однако в контексте есть два бина, которые могут быть внедрены. Для разрешения этой неоднозначности используется аннотация @Qualifier("serviceA"), которая указывает на то, что необходимо внедрить именно бин с именем serviceA.

Таким образом, в клиент будет внедрен бин, возвращаемый методом serviceA(), а не serviceB().

3. Класс Client2510

Класс Client2510 имеет конструктор, который использует внедрение через конструктор с помощью аннотации @Autowired. Этот конструктор принимает параметр типа Service2510 и использует аннотацию @Qualifier("serviceA"), что гарантирует, что в поле service будет внедрен бин serviceA.

Метод run() вызывает метод execute() внедренного сервиса, который в нашем случае является экземпляром ServiceA2510.

4. Main-класс

Основной класс программы создает Spring-контекст с использованием класса AnnotationConfigApplicationContext.

Затем:
Через context.getBean(Client2510.class) получаем экземпляр клиента с внедренным сервисом serviceA.
Вызов метода
client.run() приводит к выполнению метода execute() из класса ServiceA2510, который выводит в консоль сообщение "Service A executed".
После выполнения закрываем контекст, освобождая все ресурсы.


Ожидаемое поведение:
Аннотация @Qualifier("serviceA") указывает Spring, что нужно внедрить именно бин serviceA, а не serviceB.
Метод run() вызывает serviceA.execute(), выводя "Service A executed".


Основные выводы:

В контексте Spring можно иметь несколько бинов одного типа, и аннотация @Qualifier помогает определить, какой именно бин должен быть внедрен.
В данном примере используется конструкторное внедрение зависимостей с точным указанием, какой бин выбрать.


#Solution_TasksSpring
👍2