[Interview question] The life cycle of beans in Spring, the difference between Spring's DI and IoC

One, the life cycle of beans in Spring

class --> BeanDefinition --> new object (original object) --> property filling --> initialization --> bean join singleton pool

Bean life cycle is mainly: construction (instancing) --> property injection (set) --> before initialization --> initialization --> after initialization --> adding to the singleton pool to be used --> destroy

1. Four main stages

The life cycle of a Spring bean has only four main phases, and the others are extension points before and after these four main phases . The four phases are:

  1. Instantiation ---> construction method
  2. Attribute assignment Populate ---> setter() injection
  3. Initialization
  4. Destruction

Among them, instantiation and attribute assignment correspond to the injection of the construction method and the setter method respectively; initialization and destruction are two stages that users can customize and expand ; attribute assignment Populate is mainly used to fill dependent properties among multiple beans .

It can be found by checking the source code that they are all in the doCreateBean() method,

// 忽略了无关代码
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (instanceWrapper == null) {
       // 实例化阶段!
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }

   // Initialize the bean instance.
   Object exposedObject = bean;
   try {
       // 属性赋值阶段!
      populateBean(beanName, mbd, instanceWrapper);
       // 初始化阶段!
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }

   
   }

It can be found that three methods are called separately:

  1. createBeanInstance() -> instantiation
  2. populateBean() -> attribute assignment
  3. initializeBean() -> initialization

The destruction phase is called when the container is closed , in the close() of the ConfigurableApplicationContext class

2. Commonly used extension points

2.1 Interfaces affecting multiple beans

The two most important interfaces:

  • InstantiationAwareBeanPostProcessor : acting instantiation phase front
  • BeanPostProcessor: acting on the initialization phase before and after

Beans that implement these two interfaces will be automatically cut into the corresponding life cycle

The specific code is as follows:

package cn.xmx.ioc.lifecycle;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;

import java.beans.PropertyDescriptor;

public class MyInstantiationAwareBeanPostProcessorAdapter extends InstantiationAwareBeanPostProcessorAdapter {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if(beanName.equals("car")){
            System.out.println(beanName+"在实例化之前");
        }

        return super.postProcessBeforeInstantiation(beanClass, beanName);
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if(beanName.equals("car")){
            System.out.println(beanName+"在实例化之后");
        }
        return super.postProcessAfterInstantiation(bean, beanName);
    }
}

package cn.xmx.ioc.lifecycle;

import java.lang.reflect.Proxy;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;


//后置处理器
public class NdBeanPostProcessor implements BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
       System.out.println("NdBeanPostProcessor 在"+beanName+"对象初始化之【前】调用......");
       if(beanName.equals("car")) {
           return   new CglibInterceptor().getIntance(bean.getClass());
       }
       return bean;
        
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("NdBeanPostProcessor 在"+beanName+"对象初始化之【后】调用......");
        return bean;
    }

}

package cn.xmx.ioc.lifecycle;

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MainConfig {
    @Bean(name="car",initMethod="init",destroyMethod="destroy")
    public Car getCar() {
        return new Car("大黄蜂");
    }
    
    @Bean
    public BeanPostProcessor getBeanPostProcessor() {
        return new NdBeanPostProcessor();
    }
    @Bean
    public InstantiationAwareBeanPostProcessorAdapter getIns(){
        return new MyInstantiationAwareBeanPostProcessorAdapter();
    }
    
}

package cn.xmx.ioc.lifecycle;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/*
 四个主生命周期
         (1)实例化之前干预     InstantiationAwareBeanPostProcessorAdapter.postProcessBeforeInstantiation()
     1.实例化
          (2)实例化之后干预   InstantiationAwareBeanPostProcessorAdapter.postProcessAfterInstantiation()
     2.填充属性(给属性赋值)
     
          (1)初始化之前干预   BeanPostProcessor.postProcessBeforeInitialization()
     3.初始化化(比如准备资源文件)
             3) 属性进行干预  ----修改属性或属性值
     
         (2)初始化之后干预    BeanPostProcessor.postProcessAfterInitialization()
         
     4.销毁(释放资源---对象从内存销毁)
 N个接口
     1、干预多次
         1)BeanPostProcessor
     2、干预一次
         1)Aware
     
 */
public class TestLifeCycle {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
        Car car = (Car) context.getBean("car");
        System.out.println(car);//toString
        System.out.println("beanname:"+car.getBeanName());
        System.out.println("beanfactory:"+car.getBeanFactory());
        System.out.println("applicationContext:"+car.getApplicationContext());
    }
}

2.2 Interfaces that are only called once

2.2.1 Interfaces related to aware:

  • BeanNameAware
  • BeanFactoryAware
  • ApplicationContextAware

The entity class needs to implement these interfaces, call the setBeanName() method of the Bean to pass in the id value of the current Bean, call the setBeanFactory() method to pass in the reference of the current factory instance, and call the setApplicationContext() method to pass in the reference of the current ApplicationContext instance.
The specific code is shown below:

package cn.xmx.ioc.lifecycle;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class Car implements BeanNameAware, BeanFactoryAware, ApplicationContextAware {
    private String  name;
    private String beanName;
    private BeanFactory beanFactory;
    private ApplicationContext applicationContext;
    public void init() {
        System.out.println("car 在初始化---加载资源");
        
    }
    
    public void destroy() {
        System.out.println("car 在销毁---释放资源");
    }
    
    
    
    public Car() {
        super();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Car(String name) {
        super();
        this.name = name;
        System.out.println("car实例化了");
    }


    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("beanFactory:"+beanFactory);
        this.beanFactory = beanFactory;
    }

    public BeanFactory getBeanFactory(){
        return this.beanFactory;
    }

    public void setBeanName(String s) {
        System.out.println("beanName:"+s);
        this.beanName = s ;
    }

    public String getBeanName() {
        return this.beanName;
    }

    public ApplicationContext getApplicationContext() {
        return this.applicationContext;
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("applicationContext:"+applicationContext);
        this.applicationContext = applicationContext;
    }
}

2.2.2 Two life cycle interfaces

Both instantiation and attribute assignment are what Spring helps us to do. The two life cycle stages that can be implemented by ourselves are initialization and destruction.
1.InitializingBean corresponds to the initialization phase of the life cycle, which is called in the invokeInitMethods(beanName, wrappedBean, mbd); method of the source code.
2. DisposableBean is similar to InitializingBean, corresponding to the destruction phase of the life cycle, with the ConfigurableApplicationContext#close() method as the entrance. The implementation is to take all the beans that implement the DisposableBean interface through a loop and then call its destroy() method.

3. Summary

The entire execution process of the Bean life cycle is described as follows:

  1. If you create a class that inherits the InstantiationAwareBeanPostProcessorAdapter interface, and configure the injection of this class in the configuration file, that is, the InstantiationAwareBeanPostProcessorAdapter is associated with the bean, Spring will call the postProcessBeforeInstantiation() method of the interface.
  2. According to the configuration, call the Bean construction method or factory method to instantiate the Bean.
  3. If the InstantiationAwareBeanPostProcessorAdapter is associated with the bean, Spring will call the postProcessAfterInstantiation() method of the interface.
  4. Use dependency injection to complete configuration injection of all attribute values ​​in Bean.
  5. If the Bean implements the BeanNameAware interface, Spring calls the setBeanName() method of the Bean to pass in the id value of the current Bean.
  6. If the Bean implements the BeanFactoryAware interface, Spring calls the setBeanFactory() method to pass in the reference of the current factory instance.
  7. If the Bean implements the ApplicationContextAware interface, Spring calls the setApplicationContext() method to pass in a reference to the current ApplicationContext instance.
  8. If the BeanPostProcessor is associated with the Bean, Spring will call the pre-initialization method postProcessBeforeInitialzation() of the interface to process the Bean. This is very important here, and Spring's AOP is implemented using it.
  9. If the Bean implements the InitializingBean interface, Spring will call the afterPropertiesSet() method.
  10. If the initialization method is specified through the init-method attribute in the configuration file, the initialization method is called.
  11. If the BeanPostProcessor is associated with the Bean, Spring will call the interface initialization method postProcessAfterInitialization().
    Note: After the above work is completed, the bean can be applied later. The bean is a singleton, so in this case, we call the bean with the same id will be the instance with the same content address, of course, in the spring configuration file Non-Singleton can also be configured in.
  12. If the Bean implements the DisposableBean interface, Spring will call the destroy() method to destroy the Bean in Spring; if the destruction method of the Bean is specified through the destroy-method attribute in the configuration file, Spring will call this method to destroy the Bean.

original

2. Interview questions: The difference between Spring's DI and IOC

1. Talk about Spring IOC and DI, and their difference

IOC (Inversion of Control):

Inversion of control means that it is not responsible for the creation and maintenance of objects, and the right to manage the creation of objects is reversed to the Spring container. Created and maintained by the Spring container.

DI (Dependency Injection):

Dependency injection is embodied by two or more classes, and the object dependencies are automatically handed over to the target object (DI) for management, without the object acquiring dependencies by itself.

the difference:

  • IOC is to hand over the creation of objects to the Spring container (to manage the life cycle of the bean)
  • DI relies on the IOC container and is responsible for implementing object dependencies and creation, and does not need to be implemented through new

2. Interview: What is IoC and what is the difference between IoC and DI?

(1) IoC, also known as inversion of control, is a way of thinking, and its main focus is on the creation and management of Java objects . Compared with the traditional way, when we need an object, we don't need to directly new one, but just get one in the Spring container. At this time, we lose control of the object and only retain the right to use it. But this can also eliminate the need to focus on the management of objects.

(2) The so-called control refers to the rights of management objects.

(3) The so-called reversal refers to the management of Spring rather than the developer.

(4) IoC One of the purposes is to decouple together, when an object management vessel to a third party, the coupling between objects new way compared to conventional decreases. At the same time, Spring IoC can also reduce the cost of object management , such as implementing singleton mode (the default is singleton) and so on.

(5) It should be noted that the relationship between IoC and DI is not one, similar to the difference between interface and implementation class . IoC is a design idea, DI is an implementation of IoC , DI is also called dependency injection, in Spring You can inject the objects in the Spring container to the specified location through the @Autowired annotation.

[Note] Here is a summary of many knowledge points, not for us to memorize by rote, but to make an inductive summary after we truly understand how the bottom layer of Spring is implemented.

●The strongest Tomcat8 performance optimization in history

Why can Alibaba resist 10 billion in 90 seconds? --The evolution of server-side high-concurrency distributed architecture

B2B e-commerce platform--ChinaPay UnionPay electronic payment function

Learn Zookeeper distributed lock, let interviewers look at you with admiration

SpringCloud e-commerce spike microservice-Redisson distributed lock solution

Check out more good articles, enter the official account--please me--excellent in the past

A deep and soulful public account 0.0

 

Guess you like

Origin blog.csdn.net/a1036645146/article/details/109483928