diff --git a/spring-core-3/pom.xml b/spring-core-3/pom.xml
index 205259e8e4..d1163a174c 100644
--- a/spring-core-3/pom.xml
+++ b/spring-core-3/pom.xml
@@ -67,6 +67,12 @@
${junit-jupiter.version}
test
+
+
+ log4j
+ log4j
+ ${log4j.version}
+
@@ -83,6 +89,7 @@
2.22.1
1.3.2
2.2.2.RELEASE
+ 1.2.17
\ No newline at end of file
diff --git a/spring-core-3/src/main/java/com/baeldung/ioccontainer/bean/CustomBeanFactoryPostProcessor.java b/spring-core-3/src/main/java/com/baeldung/ioccontainer/bean/CustomBeanFactoryPostProcessor.java
new file mode 100644
index 0000000000..d6e2c92144
--- /dev/null
+++ b/spring-core-3/src/main/java/com/baeldung/ioccontainer/bean/CustomBeanFactoryPostProcessor.java
@@ -0,0 +1,16 @@
+package com.baeldung.ioccontainer.bean;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+
+public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
+ static final Logger LOGGER = LogManager.getLogger(CustomBeanPostProcessor.class.getName());
+
+ @Override
+ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+ LOGGER.info("BeanFactoryPostProcessor is Registered");
+ }
+}
diff --git a/spring-core-3/src/main/java/com/baeldung/ioccontainer/bean/CustomBeanPostProcessor.java b/spring-core-3/src/main/java/com/baeldung/ioccontainer/bean/CustomBeanPostProcessor.java
new file mode 100644
index 0000000000..bf34453388
--- /dev/null
+++ b/spring-core-3/src/main/java/com/baeldung/ioccontainer/bean/CustomBeanPostProcessor.java
@@ -0,0 +1,17 @@
+package com.baeldung.ioccontainer.bean;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+
+public class CustomBeanPostProcessor implements BeanPostProcessor {
+
+ static final Logger LOGGER = LogManager.getLogger(CustomBeanPostProcessor.class.getName());
+
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ LOGGER.info("BeanPostProcessor is Registered Before Initialization");
+ return bean;
+ }
+
+}
diff --git a/spring-core-3/src/main/java/com/baeldung/ioccontainer/bean/Student.java b/spring-core-3/src/main/java/com/baeldung/ioccontainer/bean/Student.java
new file mode 100644
index 0000000000..e32b4ecc29
--- /dev/null
+++ b/spring-core-3/src/main/java/com/baeldung/ioccontainer/bean/Student.java
@@ -0,0 +1,12 @@
+package com.baeldung.ioccontainer.bean;
+
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+public class Student {
+ static final Logger LOGGER = LogManager.getLogger(Student.class.getName());
+
+ public void postConstruct() {
+ LOGGER.info("Student Bean is initialized");
+ }
+}
diff --git a/spring-core-3/src/test/java/com/baeldung/ioccontainer/IOCContainerAppTest.java b/spring-core-3/src/test/java/com/baeldung/ioccontainer/IOCContainerAppTest.java
new file mode 100644
index 0000000000..b97aa08f80
--- /dev/null
+++ b/spring-core-3/src/test/java/com/baeldung/ioccontainer/IOCContainerAppTest.java
@@ -0,0 +1,137 @@
+package com.baeldung.ioccontainer;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.Logger;
+import org.apache.log4j.spi.LoggingEvent;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+import com.baeldung.ioccontainer.bean.CustomBeanFactoryPostProcessor;
+import com.baeldung.ioccontainer.bean.CustomBeanPostProcessor;
+import com.baeldung.ioccontainer.bean.Student;
+
+public class IOCContainerAppTest {
+
+ private LogAppender logAppender;
+ private List loggingEvents;
+
+ @BeforeEach
+ public void initializeLogAppender() {
+ logAppender = new LogAppender();
+ Logger.getRootLogger()
+ .addAppender(logAppender);
+ loggingEvents = logAppender.events;
+ }
+
+ @AfterEach
+ public void removeLogAppender() {
+ Logger.getRootLogger()
+ .removeAppender(logAppender);
+ }
+
+ @Test
+ public void whenBFInitialized_thenNoStudentLogPrinted() {
+ Resource res = new ClassPathResource("ioc-container-difference-example.xml");
+ BeanFactory factory = new XmlBeanFactory(res);
+
+ String expected = "Student Bean is initialized";
+ assertFalse(checkWhetherLoggerContains(expected));
+ }
+
+ @Test
+ public void whenBFInitialized_thenStudentLogPrinted() {
+
+ Resource res = new ClassPathResource("ioc-container-difference-example.xml");
+ BeanFactory factory = new XmlBeanFactory(res);
+ Student student = (Student) factory.getBean("student");
+
+ String expected = "Student Bean is initialized";
+ assertTrue(checkWhetherLoggerContains(expected));
+ }
+
+ @Test
+ public void whenAppContInitialized_thenStudentObjInitialized() {
+ ApplicationContext context = new ClassPathXmlApplicationContext("ioc-container-difference-example.xml");
+
+ String expected = "Student Bean is initialized";
+ assertTrue(checkWhetherLoggerContains(expected));
+ }
+
+ @Test
+ public void whenBFInitialized_thenBFPProcessorAndBPProcessorNotRegAutomatically() {
+ Resource res = new ClassPathResource("ioc-container-difference-example.xml");
+ ConfigurableListableBeanFactory factory = new XmlBeanFactory(res);
+
+ String beanFactoryPostProcessorExpectedLog = "BeanFactoryPostProcessor is Registered";
+ assertFalse(checkWhetherLoggerContains(beanFactoryPostProcessorExpectedLog));
+
+ String beanPostProcessorExpectedLog = "BeanPostProcessor is Registered Before Initialization";
+ assertFalse(checkWhetherLoggerContains(beanPostProcessorExpectedLog));
+ }
+
+ @Test
+ public void whenAppContInitialized_thenBFPostProcessorAndBPostProcessorRegisteredAutomatically() {
+ ApplicationContext context = new ClassPathXmlApplicationContext("ioc-container-difference-example.xml");
+
+ String beanFactoryPostProcessorExpectedLog = "BeanFactoryPostProcessor is Registered";
+ assertTrue(checkWhetherLoggerContains(beanFactoryPostProcessorExpectedLog));
+
+ String beanPostProcessorExpectedLog = "BeanPostProcessor is Registered Before Initialization";
+ assertTrue(checkWhetherLoggerContains(beanPostProcessorExpectedLog));
+ }
+
+ @Test
+ public void whenBFPostProcessorAndBPProcessorRegisteredManually_thenReturnTrue() {
+ Resource res = new ClassPathResource("ioc-container-difference-example.xml");
+ ConfigurableListableBeanFactory factory = new XmlBeanFactory(res);
+
+ CustomBeanFactoryPostProcessor beanFactoryPostProcessor = new CustomBeanFactoryPostProcessor();
+ beanFactoryPostProcessor.postProcessBeanFactory(factory);
+ String beanFactoryPostProcessorExpectedLog = "BeanFactoryPostProcessor is Registered";
+ assertTrue(checkWhetherLoggerContains(beanFactoryPostProcessorExpectedLog));
+
+ CustomBeanPostProcessor beanPostProcessor = new CustomBeanPostProcessor();
+ factory.addBeanPostProcessor(beanPostProcessor);
+ Student student = (Student) factory.getBean("student");
+ String beanPostProcessorExpectedLog = "BeanPostProcessor is Registered Before Initialization";
+ assertTrue(checkWhetherLoggerContains(beanPostProcessorExpectedLog));
+ }
+
+ private boolean checkWhetherLoggerContains(String expectedLogMessge) {
+ boolean isLogExist = loggingEvents.stream()
+ .anyMatch(logEvent -> logEvent.getMessage()
+ .equals(expectedLogMessge));
+ return isLogExist;
+ }
+
+ public static class LogAppender extends AppenderSkeleton {
+ public List events = new ArrayList();
+
+ public void close() {
+ }
+
+ public boolean requiresLayout() {
+ return false;
+ }
+
+ @Override
+ protected void append(LoggingEvent event) {
+ events.add(event);
+ }
+
+ }
+}
diff --git a/spring-core-3/src/test/resources/ioc-container-difference-example.xml b/spring-core-3/src/test/resources/ioc-container-difference-example.xml
new file mode 100644
index 0000000000..9bb01efe66
--- /dev/null
+++ b/spring-core-3/src/test/resources/ioc-container-difference-example.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file