diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/.gitignore b/2023-03/spring-06-bean-scopes-and-lifecycle/.gitignore
new file mode 100644
index 00000000..e62c33c2
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/.gitignore
@@ -0,0 +1,4 @@
+.idea/
+*.iml
+
+target/
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/.gitignore b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/.gitignore
new file mode 100644
index 00000000..789ddc9e
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/.gitignore
@@ -0,0 +1,32 @@
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+#other
+*.bat
+*/.idea
+*.iml
+*/target
+
+.idea
+*.iml
+target
\ No newline at end of file
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/README.md b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/README.md
new file mode 100644
index 00000000..75a9cff8
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/README.md
@@ -0,0 +1,19 @@
+#### Упражнение №2
+- Изучить классы ничего в них не меняя:
+ - CustomBeanFactoryPostProcessor
+ - CustomBeanPostProcessor
+ - CustomLifeCycleBean
+- Запуститить приложение
+- Изучить распечатанный жизненный цикл
+
+
+#### Упражнение №3
+- В application.yml выставить spring.shell.interactive.enabled в true
+- Запуститить приложение командой "cfn" или "call-favorite-number"
+- Запомнить результат
+- В CustomBeanFactoryPostProcessor раскомментировать блок кода
+- Запуститить приложение командой "cfn" или "call-favorite-number"
+- Что изменилось?
+- В CustomBeanPostProcessor раскомментировать строку
+- Запуститить приложение командой "cfn" или "call-favorite-number"
+- Что изменилось теперь? Круто, да?
\ No newline at end of file
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/pom.xml b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/pom.xml
new file mode 100644
index 00000000..f076a9fd
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/pom.xml
@@ -0,0 +1,50 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+
+ 3.0.5
+
+
+ ru.otus.example
+ beans-lifecycle-exercise
+ 0.0.1-SNAPSHOT
+
+
+
+ 17
+ 17
+ 17
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/BeansLifecycleDemoApplication.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/BeansLifecycleDemoApplication.java
new file mode 100644
index 00000000..337afceb
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/BeansLifecycleDemoApplication.java
@@ -0,0 +1,20 @@
+package ru.otus.example.beanslifecycledemo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.ApplicationContext;
+import ru.otus.example.beanslifecycledemo.domain.Phone;
+
+@SpringBootApplication
+public class BeansLifecycleDemoApplication {
+
+ public static void main(String[] args) {
+ ApplicationContext ctx = SpringApplication.run(BeansLifecycleDemoApplication.class, args);
+ try {
+ Phone phone = ctx.getBean(Phone.class);
+ phone.callFavoriteNumber();
+ }catch (Exception e) {
+ }
+ }
+
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/domain/FriendPhoneNumber.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/domain/FriendPhoneNumber.java
new file mode 100644
index 00000000..913d7db0
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/domain/FriendPhoneNumber.java
@@ -0,0 +1,8 @@
+package ru.otus.example.beanslifecycledemo.domain;
+
+public class FriendPhoneNumber extends PhoneNumber {
+ @Override
+ public String getOwnerName() {
+ return "Друг";
+ }
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/domain/GirlfiendPhoneNumber.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/domain/GirlfiendPhoneNumber.java
new file mode 100644
index 00000000..54e4e173
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/domain/GirlfiendPhoneNumber.java
@@ -0,0 +1,11 @@
+package ru.otus.example.beanslifecycledemo.domain;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class GirlfiendPhoneNumber extends PhoneNumber {
+ @Override
+ public String getOwnerName() {
+ return "Подруга";
+ }
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/domain/Phone.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/domain/Phone.java
new file mode 100644
index 00000000..81170317
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/domain/Phone.java
@@ -0,0 +1,18 @@
+package ru.otus.example.beanslifecycledemo.domain;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConditionalOnProperty(name = "lifecycle.print.enabled", havingValue = "false")
+@RequiredArgsConstructor
+public class Phone {
+ private String greeting = "Погнали к родителям";
+
+ private final PhoneNumber favoriteNumber;
+
+ public void callFavoriteNumber() {
+ System.out.println(favoriteNumber.getOwnerName() + " " + greeting);
+ }
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/domain/PhoneNumber.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/domain/PhoneNumber.java
new file mode 100644
index 00000000..215bd09f
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/domain/PhoneNumber.java
@@ -0,0 +1,7 @@
+package ru.otus.example.beanslifecycledemo.domain;
+
+public abstract class PhoneNumber {
+ public String getOwnerName() {
+ return "Спорт-лото";
+ }
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/lifecycle/CustomBeanDefinitionRegistrar.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/lifecycle/CustomBeanDefinitionRegistrar.java
new file mode 100644
index 00000000..fafd360b
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/lifecycle/CustomBeanDefinitionRegistrar.java
@@ -0,0 +1,62 @@
+package ru.otus.example.beanslifecycledemo.lifecycle;
+
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.BeanNameGenerator;
+import org.springframework.beans.factory.support.GenericBeanDefinition;
+import org.springframework.context.EnvironmentAware;
+import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
+import org.springframework.core.env.Environment;
+import org.springframework.core.type.AnnotationMetadata;
+
+import java.util.Optional;
+
+public class CustomBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {
+ private Environment environment;
+
+ @Override
+ public void setEnvironment(Environment environment) {
+ this.environment = environment;
+ }
+
+ @Override
+ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
+ BeanDefinitionRegistry registry,
+ BeanNameGenerator importBeanNameGenerator) {
+ registerBeanDefinitions(importingClassMetadata, registry);
+ }
+
+ @Override
+ public void registerBeanDefinitions(AnnotationMetadata metadata,
+ BeanDefinitionRegistry registry) {
+
+ registerBeanFactoryPostProcessor(registry);
+ registerBeanPostProcessor(registry);
+
+ if (Optional.ofNullable(environment.getProperty("lifecycle.print.enabled", Boolean.class)).orElse(false)) {
+ System.out.println("Шаг #0: ImportBeanDefinitionRegistrar.registerBeanDefinitions\n");
+ registerCustomLifeCycleBean(registry);
+ }
+
+ }
+
+ private void registerCustomLifeCycleBean(BeanDefinitionRegistry registry) {
+ GenericBeanDefinition gbd = new GenericBeanDefinition();
+ gbd.setBeanClass(CustomLifeCycleBean.class);
+ gbd.setInitMethodName("customInitMethod");
+ gbd.setDestroyMethodName("customDestroyMethod");
+ registry.registerBeanDefinition("customLifeCycleBean", gbd);
+ }
+
+ private void registerBeanFactoryPostProcessor(BeanDefinitionRegistry registry) {
+ GenericBeanDefinition gbd = new GenericBeanDefinition();
+ gbd.setBeanClass(CustomBeanFactoryPostProcessor.class);
+ registry.registerBeanDefinition("customBeanFactoryPostProcessor", gbd);
+ }
+
+ private void registerBeanPostProcessor(BeanDefinitionRegistry registry) {
+ GenericBeanDefinition gbd = new GenericBeanDefinition();
+ gbd.setBeanClass(CustomBeanPostProcessor.class);
+ registry.registerBeanDefinition("customBeanPostProcessor", gbd);
+ }
+
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/lifecycle/CustomBeanFactoryPostProcessor.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/lifecycle/CustomBeanFactoryPostProcessor.java
new file mode 100644
index 00000000..5f82e6e5
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/lifecycle/CustomBeanFactoryPostProcessor.java
@@ -0,0 +1,32 @@
+package ru.otus.example.beanslifecycledemo.lifecycle;
+
+import org.springframework.beans.BeanMetadataAttribute;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.context.annotation.ScannedGenericBeanDefinition;
+import ru.otus.example.beanslifecycledemo.domain.FriendPhoneNumber;
+import ru.otus.example.beanslifecycledemo.domain.GirlfiendPhoneNumber;
+
+public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
+ @Override
+ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+
+ if (beanFactory.containsBean("customLifeCycleBean")) {
+ System.out.println("Шаг #1: BeanFactoryPostProcessor.postProcessBeanFactory\n");
+ }
+
+/*
+ for (String beanName : beanFactory.getBeanDefinitionNames()) {
+ BeanDefinition d = beanFactory.getBeanDefinition(beanName);
+
+ if (GirlfiendPhoneNumber.class.getName().equalsIgnoreCase(d.getBeanClassName())) {
+ d.setBeanClassName(FriendPhoneNumber.class.getName());
+ ((ScannedGenericBeanDefinition) d).addMetadataAttribute(new BeanMetadataAttribute("className", FriendPhoneNumber.class.getName()));
+ d.setAutowireCandidate(true);
+ }
+ }
+*/
+ }
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/lifecycle/CustomBeanPostProcessor.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/lifecycle/CustomBeanPostProcessor.java
new file mode 100644
index 00000000..c4dc21ab
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/lifecycle/CustomBeanPostProcessor.java
@@ -0,0 +1,48 @@
+package ru.otus.example.beanslifecycledemo.lifecycle;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.InvalidPropertyException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import ru.otus.example.beanslifecycledemo.domain.Phone;
+
+import java.lang.reflect.Field;
+
+public class CustomBeanPostProcessor implements BeanPostProcessor {
+
+ public static final String GREETING_PROPERTY = "greeting";
+
+ @Override
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ if (bean.getClass().equals(CustomLifeCycleBean.class)) {
+ System.out.println("Шаг #5: BeanPostProcessor.postProcessBeforeInitialization\n");
+ }
+ return bean;
+ }
+
+ @Override
+ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+ if (bean.getClass().equals(CustomLifeCycleBean.class)) {
+ System.out.println("Шаг #9: BeanPostProcessor.postProcessAfterInitialization\n");
+ }
+
+/*
+ if (bean.getClass().isAssignableFrom(Phone.class)) {
+ updateGreeting(bean);
+ }
+*/
+ return bean;
+ }
+
+ private void updateGreeting(Object bean) {
+ Class> aClass = Phone.class;
+ try {
+ Field greetingField = aClass.getDeclaredField(GREETING_PROPERTY);
+
+ greetingField.setAccessible(true);
+ greetingField.set(bean, "Ай-да в гараж. Стихи читать!");
+ } catch (Exception e) {
+ throw new InvalidPropertyException(Phone.class, GREETING_PROPERTY,
+ "Bean class does not have expected property", e);
+ }
+ }
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/lifecycle/CustomLifeCycleBean.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/lifecycle/CustomLifeCycleBean.java
new file mode 100644
index 00000000..f89db1fd
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/lifecycle/CustomLifeCycleBean.java
@@ -0,0 +1,60 @@
+package ru.otus.example.beanslifecycledemo.lifecycle;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.*;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+/*
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+*/
+
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+
+public class CustomLifeCycleBean implements InitializingBean, DisposableBean, BeanNameAware,
+ BeanFactoryAware, ApplicationContextAware {
+
+ @Override
+ public void setBeanName(String s) {
+ System.out.println("Шаг #2: BeanNameAware\n");
+ }
+
+ @Override
+ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
+ System.out.println("Шаг #3: BeanFactoryAware\n");
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ System.out.println("Шаг #4: ApplicationContextAware\n");
+ }
+
+ @PostConstruct
+ public void postConstruct() {
+ System.out.println("Шаг #6: @PostConstruct\n");
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ System.out.println("Шаг #7: InitializingBean.afterPropertiesSet\n");
+ }
+
+ public void customInitMethod() {
+ System.out.println("Шаг #8: CustomLifeCycleBean.customInitMethod\n");
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ System.out.println("Шаг #10: @PreDestroy\n");
+ }
+
+ @Override
+ public void destroy() throws Exception {
+ System.out.println("Шаг #11: DisposableBean.destroy\n");
+ }
+
+ public void customDestroyMethod() {
+ System.out.println("Шаг #12: CustomLifeCycleBean.customDestroyMethod\n");
+ }
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/lifecycle/LifeCycleConfig.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/lifecycle/LifeCycleConfig.java
new file mode 100644
index 00000000..a1cb405b
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/java/ru/otus/example/beanslifecycledemo/lifecycle/LifeCycleConfig.java
@@ -0,0 +1,30 @@
+package ru.otus.example.beanslifecycledemo.lifecycle;
+
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+@Import(CustomBeanDefinitionRegistrar.class)
+@Configuration
+public class LifeCycleConfig {
+/*
+ @Bean
+ public BeanFactoryPostProcessor customBeanFactoryPostProcessor() {
+ return new CustomBeanFactoryPostProcessor();
+ }
+
+ @Bean
+ public BeanPostProcessor customBeanPostProcessor() {
+ return new CustomBeanPostProcessor();
+ }
+
+ @ConditionalOnProperty(name = "lifecycle.print.enabled", havingValue = "true")
+ @Bean(initMethod = "customInitMethod", destroyMethod = "customDestroyMethod")
+ public CustomLifeCycleBean customLifeCycleBean() {
+ return new CustomLifeCycleBean();
+ }
+*/
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/resources/application.yml b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/resources/application.yml
new file mode 100644
index 00000000..54b14aef
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-lifecycle-exercise/src/main/resources/application.yml
@@ -0,0 +1,7 @@
+logging:
+ level:
+ root: ERROR
+
+lifecycle:
+ print:
+ enabled: true
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/.gitignore b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/.gitignore
new file mode 100644
index 00000000..789ddc9e
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/.gitignore
@@ -0,0 +1,32 @@
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+#other
+*.bat
+*/.idea
+*.iml
+*/target
+
+.idea
+*.iml
+target
\ No newline at end of file
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/README.md b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/README.md
new file mode 100644
index 00000000..2a7c2a04
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/README.md
@@ -0,0 +1,9 @@
+#### Упражнение №1
+- Расставить скоупы над сервисами так, чтобы приложение запустилось и заработало, как указано на странице http://localhost:8080
+- Подсказки в названии сервисов
+- Не забываем про proxyMode для некоторых скоупов
+
+```
+Задать скоуп можно с помощью аннотации @Scope
+Возможные значения: singleton, prototype, session, request
+```
\ No newline at end of file
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/pom.xml b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/pom.xml
new file mode 100644
index 00000000..276ebe53
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+
+ 3.0.5
+
+
+
+ ru.otus.example
+ beans-scopes-exercise
+ 0.0.1-SNAPSHOT
+
+
+
+ 17
+ 17
+ 17
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/BeansScopesDemoApplication.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/BeansScopesDemoApplication.java
new file mode 100644
index 00000000..b482b9a7
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/BeansScopesDemoApplication.java
@@ -0,0 +1,15 @@
+package ru.otus.example.beansscopesdemo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class BeansScopesDemoApplication {
+
+ public static void main(String[] args) {
+ var ctx = SpringApplication.run(BeansScopesDemoApplication.class, args);
+ var serverPort = ctx.getEnvironment().getProperty("local.server.port");
+ System.out.printf("Чтобы смотреть результат переходи сюда: http://localhost:%s", serverPort);
+ }
+
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/controllers/GreetingController.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/controllers/GreetingController.java
new file mode 100644
index 00000000..6bfc91c1
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/controllers/GreetingController.java
@@ -0,0 +1,41 @@
+package ru.otus.example.beansscopesdemo.controllers;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import ru.otus.example.beansscopesdemo.services.GreetingService;
+
+@Controller
+public class GreetingController {
+ private final GreetingService singletonGreetingService;
+ private final GreetingService prototypeGreetingService1;
+ private final GreetingService prototypeGreetingService2;
+ private final GreetingService sessionGreetingService;
+ private final GreetingService requestGreetingService;
+
+ public GreetingController(GreetingService singletonGreetingService,
+ @Qualifier("prototypeGreetingService")
+ GreetingService prototypeGreetingService1,
+ @Qualifier("prototypeGreetingService")
+ GreetingService prototypeGreetingService2,
+ GreetingService sessionGreetingService,
+ GreetingService requestGreetingService
+ ) {
+ this.singletonGreetingService = singletonGreetingService;
+ this.prototypeGreetingService1 = prototypeGreetingService1;
+ this.prototypeGreetingService2 = prototypeGreetingService2;
+ this.sessionGreetingService = sessionGreetingService;
+ this.requestGreetingService = requestGreetingService;
+ }
+
+ @GetMapping("/")
+ public String greetingPage(Model model) {
+ model.addAttribute("singletonGreeting", singletonGreetingService.greeting());
+ model.addAttribute("sessionGreeting", sessionGreetingService.greeting());
+ model.addAttribute("requestGreeting", requestGreetingService.greeting());
+ model.addAttribute("prototype1Greeting", prototypeGreetingService1.greeting());
+ model.addAttribute("prototype2Greeting", prototypeGreetingService2.greeting());
+ return "index";
+ }
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/AbstractGreetingServiceImpl.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/AbstractGreetingServiceImpl.java
new file mode 100644
index 00000000..3199df44
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/AbstractGreetingServiceImpl.java
@@ -0,0 +1,23 @@
+package ru.otus.example.beansscopesdemo.services;
+
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+public abstract class AbstractGreetingServiceImpl implements GreetingService {
+
+ private final AtomicInteger counter;
+
+ public AbstractGreetingServiceImpl() {
+ this.counter = new AtomicInteger(0);
+ }
+
+ @Override
+ public String greeting() {
+ return currentGreeting();
+ }
+
+ private String currentGreeting() {
+ return String.format("Привет! Это наша встреча №%d. Меня зовут: %s",
+ counter.incrementAndGet(), Integer.toHexString(hashCode()));
+ }
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/GreetingService.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/GreetingService.java
new file mode 100644
index 00000000..3fb338b1
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/GreetingService.java
@@ -0,0 +1,5 @@
+package ru.otus.example.beansscopesdemo.services;
+
+public interface GreetingService {
+ String greeting();
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/PrototypeGreetingServiceImpl.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/PrototypeGreetingServiceImpl.java
new file mode 100644
index 00000000..cb30816b
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/PrototypeGreetingServiceImpl.java
@@ -0,0 +1,7 @@
+package ru.otus.example.beansscopesdemo.services;
+
+import org.springframework.stereotype.Service;
+
+@Service("prototypeGreetingService")
+public class PrototypeGreetingServiceImpl extends AbstractGreetingServiceImpl {
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/RequestGreetingServiceImpl.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/RequestGreetingServiceImpl.java
new file mode 100644
index 00000000..0631f2da
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/RequestGreetingServiceImpl.java
@@ -0,0 +1,7 @@
+package ru.otus.example.beansscopesdemo.services;
+
+import org.springframework.stereotype.Service;
+
+@Service("requestGreetingService")
+public class RequestGreetingServiceImpl extends AbstractGreetingServiceImpl {
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/SessionGreetingServiceImpl.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/SessionGreetingServiceImpl.java
new file mode 100644
index 00000000..47ea143c
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/SessionGreetingServiceImpl.java
@@ -0,0 +1,7 @@
+package ru.otus.example.beansscopesdemo.services;
+
+import org.springframework.stereotype.Service;
+
+@Service("sessionGreetingService")
+public class SessionGreetingServiceImpl extends AbstractGreetingServiceImpl {
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/SingletonGreetingServiceImpl.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/SingletonGreetingServiceImpl.java
new file mode 100644
index 00000000..70b6a266
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/java/ru/otus/example/beansscopesdemo/services/SingletonGreetingServiceImpl.java
@@ -0,0 +1,7 @@
+package ru.otus.example.beansscopesdemo.services;
+
+import org.springframework.stereotype.Service;
+
+@Service("singletonGreetingService")
+public class SingletonGreetingServiceImpl extends AbstractGreetingServiceImpl {
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/resources/application.yml b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/resources/application.yml
new file mode 100644
index 00000000..f78a9f36
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/resources/application.yml
@@ -0,0 +1,3 @@
+logging:
+ level:
+ root: ERROR
\ No newline at end of file
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/resources/templates/index.html b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/resources/templates/index.html
new file mode 100644
index 00000000..601ae82e
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-exercise/src/main/resources/templates/index.html
@@ -0,0 +1,45 @@
+
+
+
+
+ Advanced configuration demo
+
+
+
+
+
Демонстрация @Scope
+
+ - Singleton должен постоянно накручивать счетчик встреч и не менять имя
+ - Prototype1 должен вести себя так же, как и Singleton, но иметь имя отличное от Prototype2
+ - Prototype2 должен вести себя так же, как и Singleton, но иметь имя отличное от Prototype1
+ - Session должен вести себя как Singleton, но только до перезапуска браузера. После, счетчик встреч должен пойти заново
+ - Request должен всегда показывать первую встречу и разное имя
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/.gitignore b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/.gitignore
new file mode 100644
index 00000000..789ddc9e
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/.gitignore
@@ -0,0 +1,32 @@
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+#other
+*.bat
+*/.idea
+*.iml
+*/target
+
+.idea
+*.iml
+target
\ No newline at end of file
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/README.md b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/README.md
new file mode 100644
index 00000000..b02345e6
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/README.md
@@ -0,0 +1,15 @@
+#### Решение к упражнению №1
+
+@Scope("singleton")
+SingletonGreetingServiceImpl
+
+@Scope("prototype")
+PrototypeGreetingServiceImpl
+
+@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
+RequestGreetingServiceImpl
+
+@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
+SessionGreetingServiceImpl
+
+
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/pom.xml b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/pom.xml
new file mode 100644
index 00000000..da6d592b
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+
+ 3.0.5
+
+
+
+ ru.otus.example
+ beans-scopes-solution
+ 0.0.1-SNAPSHOT
+
+
+
+ 17
+ 17
+ 17
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/BeansScopesDemoApplication.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/BeansScopesDemoApplication.java
new file mode 100644
index 00000000..b482b9a7
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/BeansScopesDemoApplication.java
@@ -0,0 +1,15 @@
+package ru.otus.example.beansscopesdemo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class BeansScopesDemoApplication {
+
+ public static void main(String[] args) {
+ var ctx = SpringApplication.run(BeansScopesDemoApplication.class, args);
+ var serverPort = ctx.getEnvironment().getProperty("local.server.port");
+ System.out.printf("Чтобы смотреть результат переходи сюда: http://localhost:%s", serverPort);
+ }
+
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/controllers/GreetingController.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/controllers/GreetingController.java
new file mode 100644
index 00000000..6bfc91c1
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/controllers/GreetingController.java
@@ -0,0 +1,41 @@
+package ru.otus.example.beansscopesdemo.controllers;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import ru.otus.example.beansscopesdemo.services.GreetingService;
+
+@Controller
+public class GreetingController {
+ private final GreetingService singletonGreetingService;
+ private final GreetingService prototypeGreetingService1;
+ private final GreetingService prototypeGreetingService2;
+ private final GreetingService sessionGreetingService;
+ private final GreetingService requestGreetingService;
+
+ public GreetingController(GreetingService singletonGreetingService,
+ @Qualifier("prototypeGreetingService")
+ GreetingService prototypeGreetingService1,
+ @Qualifier("prototypeGreetingService")
+ GreetingService prototypeGreetingService2,
+ GreetingService sessionGreetingService,
+ GreetingService requestGreetingService
+ ) {
+ this.singletonGreetingService = singletonGreetingService;
+ this.prototypeGreetingService1 = prototypeGreetingService1;
+ this.prototypeGreetingService2 = prototypeGreetingService2;
+ this.sessionGreetingService = sessionGreetingService;
+ this.requestGreetingService = requestGreetingService;
+ }
+
+ @GetMapping("/")
+ public String greetingPage(Model model) {
+ model.addAttribute("singletonGreeting", singletonGreetingService.greeting());
+ model.addAttribute("sessionGreeting", sessionGreetingService.greeting());
+ model.addAttribute("requestGreeting", requestGreetingService.greeting());
+ model.addAttribute("prototype1Greeting", prototypeGreetingService1.greeting());
+ model.addAttribute("prototype2Greeting", prototypeGreetingService2.greeting());
+ return "index";
+ }
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/AbstractGreetingServiceImpl.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/AbstractGreetingServiceImpl.java
new file mode 100644
index 00000000..3199df44
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/AbstractGreetingServiceImpl.java
@@ -0,0 +1,23 @@
+package ru.otus.example.beansscopesdemo.services;
+
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+public abstract class AbstractGreetingServiceImpl implements GreetingService {
+
+ private final AtomicInteger counter;
+
+ public AbstractGreetingServiceImpl() {
+ this.counter = new AtomicInteger(0);
+ }
+
+ @Override
+ public String greeting() {
+ return currentGreeting();
+ }
+
+ private String currentGreeting() {
+ return String.format("Привет! Это наша встреча №%d. Меня зовут: %s",
+ counter.incrementAndGet(), Integer.toHexString(hashCode()));
+ }
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/GreetingService.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/GreetingService.java
new file mode 100644
index 00000000..3fb338b1
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/GreetingService.java
@@ -0,0 +1,5 @@
+package ru.otus.example.beansscopesdemo.services;
+
+public interface GreetingService {
+ String greeting();
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/PrototypeGreetingServiceImpl.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/PrototypeGreetingServiceImpl.java
new file mode 100644
index 00000000..6b29df8d
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/PrototypeGreetingServiceImpl.java
@@ -0,0 +1,10 @@
+package ru.otus.example.beansscopesdemo.services;
+
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.ScopedProxyMode;
+import org.springframework.stereotype.Service;
+
+@Scope(scopeName = "prototype")
+@Service("prototypeGreetingService")
+public class PrototypeGreetingServiceImpl extends AbstractGreetingServiceImpl {
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/RequestGreetingServiceImpl.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/RequestGreetingServiceImpl.java
new file mode 100644
index 00000000..a216003d
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/RequestGreetingServiceImpl.java
@@ -0,0 +1,11 @@
+package ru.otus.example.beansscopesdemo.services;
+
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.ScopedProxyMode;
+import org.springframework.stereotype.Service;
+import org.springframework.web.context.WebApplicationContext;
+
+@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
+@Service("requestGreetingService")
+public class RequestGreetingServiceImpl extends AbstractGreetingServiceImpl {
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/SessionGreetingServiceImpl.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/SessionGreetingServiceImpl.java
new file mode 100644
index 00000000..35e17d21
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/SessionGreetingServiceImpl.java
@@ -0,0 +1,11 @@
+package ru.otus.example.beansscopesdemo.services;
+
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.ScopedProxyMode;
+import org.springframework.stereotype.Service;
+import org.springframework.web.context.WebApplicationContext;
+
+@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
+@Service("sessionGreetingService")
+public class SessionGreetingServiceImpl extends AbstractGreetingServiceImpl {
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/SingletonGreetingServiceImpl.java b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/SingletonGreetingServiceImpl.java
new file mode 100644
index 00000000..4c9825da
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/java/ru/otus/example/beansscopesdemo/services/SingletonGreetingServiceImpl.java
@@ -0,0 +1,9 @@
+package ru.otus.example.beansscopesdemo.services;
+
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Service;
+
+@Scope("singleton")
+@Service("singletonGreetingService")
+public class SingletonGreetingServiceImpl extends AbstractGreetingServiceImpl {
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/resources/application.yml b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/resources/application.yml
new file mode 100644
index 00000000..f78a9f36
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/resources/application.yml
@@ -0,0 +1,3 @@
+logging:
+ level:
+ root: ERROR
\ No newline at end of file
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/resources/templates/index.html b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/resources/templates/index.html
new file mode 100644
index 00000000..3f9e21dc
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/beans-scopes-solution/src/main/resources/templates/index.html
@@ -0,0 +1,45 @@
+
+
+
+
+ Advanced configuration demo
+
+
+
+
+
Демонстрация @Scope
+
+ - Singleton должен постоянно накручивать счетчик встреч и не менять имя
+ - Prototype1 должен вести себя так же, как и Singleton, но иметь имя отличное от Prototype2
+ - Prototype2 должен вести себя так же, как и Singleton, но иметь имя отличное от Prototype1
+ - Session должен вести себя как Singleton, но только до перезапуска браузера. После, счетчик встреч должен пойти заново
+ - Request должен всегда показывать первую встречу и разное имя
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/.gitignore b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/.gitignore
new file mode 100644
index 00000000..549e00a2
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/README.md b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/README.md
new file mode 100644
index 00000000..edbd8776
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/README.md
@@ -0,0 +1,3 @@
+#### Демо создания собственного Scope
+
+В зависимости от значения поля `canTakeVacation` класса `VacationCalendar`, бин отпуска либо доступен, либо нет
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/pom.xml b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/pom.xml
new file mode 100644
index 00000000..8818a51c
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/pom.xml
@@ -0,0 +1,51 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+
+ 3.0.5
+
+
+ ru.otus
+ custom-scope-demo
+ 0.0.1-SNAPSHOT
+ custom-scope-demo
+ Custom scope demo
+
+
+ 17
+ 17
+ 17
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/CustomScopeDemoApplication.java b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/CustomScopeDemoApplication.java
new file mode 100644
index 00000000..d33a3788
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/CustomScopeDemoApplication.java
@@ -0,0 +1,28 @@
+package ru.otus.customscopedemo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import ru.otus.customscopedemo.scope.VacationDoesNotAvailableException;
+import ru.otus.customscopedemo.vacation.Vacation;
+import ru.otus.customscopedemo.vacation.VacationCalendar;
+
+@SpringBootApplication
+public class CustomScopeDemoApplication {
+ private static final Logger logger = LoggerFactory.getLogger(CustomScopeDemoApplication.class);
+
+ public static void main(String[] args) {
+ var ctx = SpringApplication.run(CustomScopeDemoApplication.class, args);
+ var vacationCalendar = ctx.getBean(VacationCalendar.class);
+ var vacation = ctx.getBean(Vacation.class);
+
+ vacationCalendar.setCanTakeVacation(true);
+ try {
+ vacation.enjoy();
+ } catch (VacationDoesNotAvailableException e) {
+ logger.info("Извини Добби, твой отпуск в другом замке!");
+ }
+ }
+
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/scope/VacationDoesNotAvailableException.java b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/scope/VacationDoesNotAvailableException.java
new file mode 100644
index 00000000..2e5d915c
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/scope/VacationDoesNotAvailableException.java
@@ -0,0 +1,4 @@
+package ru.otus.customscopedemo.scope;
+
+public class VacationDoesNotAvailableException extends RuntimeException {
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/scope/VacationScope.java b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/scope/VacationScope.java
new file mode 100644
index 00000000..ca542f6d
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/scope/VacationScope.java
@@ -0,0 +1,70 @@
+package ru.otus.customscopedemo.scope;
+
+import org.springframework.beans.factory.ObjectFactory;
+import org.springframework.beans.factory.config.Scope;
+import ru.otus.customscopedemo.vacation.VacationCalendar;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+public class VacationScope implements Scope {
+
+ private final Map destructionCallbacks;
+ private final Map contextualObjects;
+
+ private final VacationCalendar vacationCalendar;
+
+ public VacationScope(VacationCalendar vacationCalendar) {
+ this.destructionCallbacks = new HashMap<>();
+ this.contextualObjects = new HashMap<>();
+ this.vacationCalendar = vacationCalendar;
+ }
+
+ // This is the central operation of a Scope, and the only operation that is absolutely required.
+ @Override
+ public Object get(String name, ObjectFactory> objectFactory) {
+ var res = resolveContextualObject(name);
+ if (res != null) {
+ return res;
+ }
+
+ if (vacationCalendar.isCanTakeVacation()) {
+ res = objectFactory.getObject();
+ contextualObjects.put(name, res);
+ return res;
+ }
+
+ throw new VacationDoesNotAvailableException();
+ }
+
+ // Note: This is an optional operation. Implementations may throw UnsupportedOperationException
+ // if they do not support explicitly removing an object.
+ @Override
+ public Object remove(String name) {
+ destructionCallbacks.remove(name);
+ return contextualObjects.remove(name);
+ }
+
+ @Override
+ public void registerDestructionCallback(String name, Runnable runnable) {
+ destructionCallbacks.put(name, runnable);
+ }
+
+ @Override
+ public Object resolveContextualObject(String name) {
+ if (!vacationCalendar.isCanTakeVacation() && contextualObjects.containsKey(name)) {
+ remove(name);
+ }
+ return contextualObjects.get(name);
+ }
+
+ @Override
+ public String getConversationId() {
+ return null;
+ }
+
+ public void onDestroy() {
+ destructionCallbacks.values().forEach(Runnable::run);
+ }
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/scope/VacationScopeConfig.java b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/scope/VacationScopeConfig.java
new file mode 100644
index 00000000..baf3be74
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/scope/VacationScopeConfig.java
@@ -0,0 +1,22 @@
+package ru.otus.customscopedemo.scope;
+
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.DependsOn;
+import ru.otus.customscopedemo.vacation.VacationCalendar;
+
+@Configuration
+public class VacationScopeConfig {
+
+ @Bean(destroyMethod = "onDestroy")
+ public VacationScope vacationScope(VacationCalendar vacationCalendar){
+ return new VacationScope(vacationCalendar);
+ }
+
+ @DependsOn("vacationScope")
+ @Bean
+ public BeanFactoryPostProcessor vacationScopeRegistrationBeanFactoryPostProcessor(VacationScope vacationScope) {
+ return new VacationScopeRegistrationBeanFactoryPostProcessor(vacationScope);
+ }
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/scope/VacationScopeRegistrationBeanFactoryPostProcessor.java b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/scope/VacationScopeRegistrationBeanFactoryPostProcessor.java
new file mode 100644
index 00000000..4a6c3dc6
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/scope/VacationScopeRegistrationBeanFactoryPostProcessor.java
@@ -0,0 +1,19 @@
+package ru.otus.customscopedemo.scope;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+
+public class VacationScopeRegistrationBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
+
+ private final VacationScope scope;
+
+ public VacationScopeRegistrationBeanFactoryPostProcessor(VacationScope scope) {
+ this.scope = scope;
+ }
+
+ @Override
+ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+ beanFactory.registerScope("vacation", scope);
+ }
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/vacation/Vacation.java b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/vacation/Vacation.java
new file mode 100644
index 00000000..531e1ef4
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/vacation/Vacation.java
@@ -0,0 +1,48 @@
+package ru.otus.customscopedemo.vacation;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.ScopedProxyMode;
+import org.springframework.stereotype.Component;
+
+//import javax.annotation.PreDestroy;
+import jakarta.annotation.PreDestroy;
+import java.time.LocalDateTime;
+import java.util.Random;
+
+@Scope(value = "vacation", proxyMode = ScopedProxyMode.TARGET_CLASS)
+@Component
+public class Vacation {
+
+ private static final Logger logger = LoggerFactory.getLogger(Vacation.class);
+
+ private static final String[] actions = {"спит", "ест", "пьет"};
+ private static final int VACATION_DURATION_SECONDS = 4;
+
+ public void enjoy(){
+ logger.info("Отпуск начат");
+ var random = new Random();
+ var startTime = LocalDateTime.now().plusSeconds(VACATION_DURATION_SECONDS);
+ while (LocalDateTime.now().isBefore(startTime)) {
+ var actionIndex = random.nextInt(3);
+ logger.info("Отдыхающий - {}", actions[actionIndex]);
+ sleep();
+ }
+ logger.info("Отпуск закончен (гаснет свет)");
+ }
+
+ private void sleep() {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @PreDestroy
+ private void destroyMethod(){
+ logger.info("Бин отпуска уничтожен");
+ }
+
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/vacation/VacationCalendar.java b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/vacation/VacationCalendar.java
new file mode 100644
index 00000000..fb8a423b
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/java/ru/otus/customscopedemo/vacation/VacationCalendar.java
@@ -0,0 +1,21 @@
+package ru.otus.customscopedemo.vacation;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+public class VacationCalendar {
+ private static final Logger logger = LoggerFactory.getLogger(VacationCalendar.class);
+
+ private boolean canTakeVacation = false;
+
+ public boolean isCanTakeVacation() {
+ return canTakeVacation;
+ }
+
+ public void setCanTakeVacation(boolean canTakeVacation) {
+ logger.info("Заявление на отпуск {}", canTakeVacation? "одобрено": "отклонено");
+ this.canTakeVacation = canTakeVacation;
+ }
+}
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/resources/application.yml b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/resources/application.yml
new file mode 100644
index 00000000..ac4fd192
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/custom-scope-demo/src/main/resources/application.yml
@@ -0,0 +1,3 @@
+spring:
+ main:
+ allow-circular-references: true
diff --git a/2023-03/spring-06-bean-scopes-and-lifecycle/pom.xml b/2023-03/spring-06-bean-scopes-and-lifecycle/pom.xml
new file mode 100644
index 00000000..4eb4f7a9
--- /dev/null
+++ b/2023-03/spring-06-bean-scopes-and-lifecycle/pom.xml
@@ -0,0 +1,19 @@
+
+
+ 4.0.0
+
+ ru.otus
+ advanced-config-class-work
+ 1.0
+
+ pom
+
+
+ beans-scopes-exercise
+ beans-scopes-solution
+ beans-lifecycle-exercise
+ custom-scope-demo
+
+