From 72c261cf1444844cc97cbbf1f68a43498e0d8519 Mon Sep 17 00:00:00 2001 From: andrewpikozh <66901090+andrewpikozh@users.noreply.github.com> Date: Wed, 29 Nov 2023 23:12:43 +0200 Subject: [PATCH] BLZT-71 add PostConstruct functionality * BLZT-71 add annotation * BLZT-71 add PostConstruct functionality * BLZT-71 refactoring * BLZT-71 add documentation * BLZT-71 fix imports in ReflectionUtils * BLZT-71 fixes --- Core.md | 14 ++-- .../bring/core/annotation/PostConstruct.java | 58 ++++++++++++++++ .../impl/PostConstructBeanPostProcessor.java | 28 ++++++++ .../exception/PostConstructException.java | 8 +++ .../bring/core/utils/ReflectionUtils.java | 10 +++ .../PostConstructBeanPostProcessorTest.java | 37 +++++++++++ .../negative/CustomPostConstruct.java | 17 +++++ .../positive/CustomPostConstruct.java | 17 +++++ features/core/PostConstruct.md | 66 +++++++++++++++++++ 9 files changed, 248 insertions(+), 7 deletions(-) create mode 100644 core/src/main/java/com/bobocode/bring/core/annotation/PostConstruct.java create mode 100644 core/src/main/java/com/bobocode/bring/core/bpp/impl/PostConstructBeanPostProcessor.java create mode 100644 core/src/main/java/com/bobocode/bring/core/exception/PostConstructException.java create mode 100644 core/src/test/java/com/bobocode/bring/core/bpp/impl/PostConstructBeanPostProcessorTest.java create mode 100644 core/src/test/java/testdata/postconstruct/negative/CustomPostConstruct.java create mode 100644 core/src/test/java/testdata/postconstruct/positive/CustomPostConstruct.java create mode 100644 features/core/PostConstruct.md diff --git a/Core.md b/Core.md index d134be2d..0e835089 100644 --- a/Core.md +++ b/Core.md @@ -22,14 +22,14 @@ It initializes the list with default post-processors such as the ScheduleBeanPos If we need diagram classes we should use Wiki and add link to it. - Dependency Injection - - [Constructor](core/Constructor.md) - - [Setter](core/Setter.md) - - [Field](core/Field.md) + - [Constructor](/features/core/Constructor.md) + - [Setter](/features/core/Setter.md) + - [Field](/features/core/Field.md) - Collections - @Primary - @Qualifier - @Order - - [@Value](core/Value.md) + - [@Value](/features/core/Value.md) - Prototype Beans into a Singleton @@ -40,7 +40,7 @@ If we need diagram classes we should use Wiki and add link to it. - Dependency Injection exceptions - - [Circular Dependencies](core/CircularDependencies.md) + - [Circular Dependencies](/features/core/CircularDependencies.md) - No such bean exception - No unique bean exception - No constructor with Autowired annotation @@ -48,7 +48,7 @@ If we need diagram classes we should use Wiki and add link to it. - addition items: - - [Scheduling](core/Scheduling.md) + - [Scheduling](/features/core/Scheduling.md) - Properties file support @@ -60,6 +60,6 @@ If we need diagram classes we should use Wiki and add link to it. - [Logging](/features/core/Logging.md) - - PostConstruct + - [@PostConstruct](/features/core/PostConstruct.md) - PreDestroy - Logo \ No newline at end of file diff --git a/core/src/main/java/com/bobocode/bring/core/annotation/PostConstruct.java b/core/src/main/java/com/bobocode/bring/core/annotation/PostConstruct.java new file mode 100644 index 00000000..e97681f5 --- /dev/null +++ b/core/src/main/java/com/bobocode/bring/core/annotation/PostConstruct.java @@ -0,0 +1,58 @@ +package com.bobocode.bring.core.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + *
The {@code PostConstruct} annotation is used on a method that needs + * to be executed after dependency injection is done to perform any + * initialization. This method is called immediately after the bean's + * properties have been set and the bean has been placed into the + * Bring container.
+ * + *Methods annotated with {@code @PostConstruct} are invoked only once + * in the bean's lifecycle, and they provide a convenient way to + * initialize resources or perform any setup logic that is required + * before the bean is ready for use.
+ * + *The method annotated with {@code @PostConstruct} must be non-static + * and should not have any parameters, as it is meant to be an + * initialization callback method for the bean instance. If multiple + * methods are annotated with {@code @PostConstruct} within a single + * class, the order of execution is not guaranteed.
+ * + *Example:
+ *+ * {@code + * import com.bobocode.bring.core.annotation.PostConstruct; + * + * public class ExampleBean { + * + * private String message; + * + * @PostConstruct + * public void init() { + * message = "Hello, this is an example!"; + * // Additional initialization logic + * } + * + * public String getMessage() { + * return message; + * } + * } + * } + *+ * + *
In this example, the {@code init} method will be automatically + * invoked after the {@code ExampleBean} is constructed, providing a + * way to perform custom initialization logic.
+ * + * @author Blyzhnytsia Team + * @since 1.0 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface PostConstruct { +} diff --git a/core/src/main/java/com/bobocode/bring/core/bpp/impl/PostConstructBeanPostProcessor.java b/core/src/main/java/com/bobocode/bring/core/bpp/impl/PostConstructBeanPostProcessor.java new file mode 100644 index 00000000..2ba3bd16 --- /dev/null +++ b/core/src/main/java/com/bobocode/bring/core/bpp/impl/PostConstructBeanPostProcessor.java @@ -0,0 +1,28 @@ +package com.bobocode.bring.core.bpp.impl; + +import com.bobocode.bring.core.annotation.BeanProcessor; +import com.bobocode.bring.core.annotation.PostConstruct; +import com.bobocode.bring.core.bpp.BeanPostProcessor; +import com.bobocode.bring.core.exception.PostConstructException; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; + +import static com.bobocode.bring.core.utils.ReflectionUtils.processBeanPostProcessorAnnotation; + + +@BeanProcessor +public class PostConstructBeanPostProcessor implements BeanPostProcessor { + + @Override + public Object postProcessInitialization(Object bean, String beanName) { + Method[] declaredMethods = bean.getClass().getMethods(); + try { + processBeanPostProcessorAnnotation(bean, declaredMethods, PostConstruct.class); + } catch (Exception exception) { + throw new PostConstructException(exception); + } + + return BeanPostProcessor.super.postProcessInitialization(bean, beanName); + } +} diff --git a/core/src/main/java/com/bobocode/bring/core/exception/PostConstructException.java b/core/src/main/java/com/bobocode/bring/core/exception/PostConstructException.java new file mode 100644 index 00000000..636a7c8a --- /dev/null +++ b/core/src/main/java/com/bobocode/bring/core/exception/PostConstructException.java @@ -0,0 +1,8 @@ +package com.bobocode.bring.core.exception; + +public class PostConstructException extends RuntimeException { + public static String POST_CONSTRUCT_EXCEPTION_MESSAGE ="@PostConstruct should be added to method without parameters"; + public PostConstructException(Throwable cause) { + super(POST_CONSTRUCT_EXCEPTION_MESSAGE, cause); + } +} diff --git a/core/src/main/java/com/bobocode/bring/core/utils/ReflectionUtils.java b/core/src/main/java/com/bobocode/bring/core/utils/ReflectionUtils.java index 5869f088..319b20dc 100644 --- a/core/src/main/java/com/bobocode/bring/core/utils/ReflectionUtils.java +++ b/core/src/main/java/com/bobocode/bring/core/utils/ReflectionUtils.java @@ -143,6 +143,16 @@ public static Supplier