More than a year later, after mastering Spring, Spring Boot and Spring Cloud
I'll go back and learn the Spring framework again.
Bean's life cycle learning:
In traditional XML configurations, initialization and destruction methods can be customized as follows:
init-method="" destroy-method=""
Simple use of annotations:
@Configuration public class LifeCircleConfig { @Bean(initMethod = "init",destroyMethod = "destroy") public Car car(){ return new Car(); } }
public class Car { public Car(){ System.out.println("Construct Car!"); } public void init(){ System.out.println("Car init!"); } public void destroy(){ System.out.println("Car destroy!"); } }
public class LifeCircleTest { private static AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(LifeCircleConfig.class); @Test public void test(){ applicationContext.close(); } }
Note: There is a close method, otherwise the Car destruction method will not be printed.
Print as follows:
Construct Car! Car init! Car destroy!
The default here is a single instance Bean
If there are multiple instances, the above test code will not print, because in the case of multiple instances, the object will be created only if the Bean is captured.
In many cases, only initialization and construction methods are invoked, and destruction methods are not invoked.
The above test code only completes the initialization of the IOC container, so nothing is printed.
Implementing interfaces in Spring: There is no need to configure in @Bean at this time
public class Car implements InitializingBean, DisposableBean { public Car() { System.out.println("Construct Car!"); } public void afterPropertiesSet() throws Exception { System.out.println("Car init!"); } public void destroy() { System.out.println("Car destroy!"); } }
Using Java native annotations:
public class Car { public Car() { System.out.println("Construct Car!"); } @PostConstruct public void init() { System.out.println("Car init!"); } @PreDestroy public void destroy() { System.out.println("Car destroy!"); } }
Using Bean's post processor in Spring:
@Component public class MyBeanPostProcessor implements BeanPostProcessor { /** * Pre-initialization call */ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessBeforeInitialization " + bean + " " + beanName); return bean; } /** * Initialized call */ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessAfterInitialization " + bean + " " + beanName); return bean; } }
@Configuration @ComponentScan("org.dreamtech.bean") public class LifeCircleConfig { @Bean public Car car(){ return new Car(); } }
After the test, the part is printed as follows:
Construct Car!
postProcessBeforeInitialization org.dreamtech.bean.Car@2d9d4f9d car
postProcessAfterInitialization org.dreamtech.bean.Car@2d9d4f9d car
BeanPost Processor Principle:
Look at this source code:
In the initializeBean(beanName, exposedObject, mbd) method:
Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); }
Before invokeInitMethods initialization method
ApplyBeanPostProcessors BeforeInitialization is called, that is, the Before method of all PostProcessors is called.
After invokeInitMethods initialization method
ApplyBeanPostProcessors AfterInitialization is called, that is, all PostProcessor's AfterInitialization methods are called.
Enter the applyBeanPostProcessors BeforeInitialization method to view the source code:
Traversing through all Processor s, once you return to null, you jump out of the loop
@Override public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessBeforeInitialization(result, beanName); if (result == null) { return result; } } return result; }
Before the initializeBean method, the populateBean method was called
Function: assign values to attributes
// Initialize the bean instance. Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { exposedObject = initializeBean(beanName, exposedObject, mbd); } }
So: BeanPostProcessor is executed before and after Bean assignment and initialization
BeanPost Processor's use at the bottom of Spring:
Get the interface of the IOC container:
public interface ApplicationContextAware extends Aware { void setApplicationContext(ApplicationContext var1) throws BeansException; }
It's based on BeanPostProcessor, and code is too long to intercept.
class ApplicationContextAwareProcessor implements BeanPostProcessor
Or parameter validation: BeanPostProcessor is also used
public class BeanValidationPostProcessor implements BeanPostProcessor, InitializingBean
Part of the code is as follows:
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (!this.afterInitialization) { this.doValidate(bean); } return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (this.afterInitialization) { this.doValidate(bean); } return bean; }