In-depth study of Spring Bean life cycle

The so-called life cycle of Spring Bean refers to the process of Bean from creation to initialization to destruction. This process is managed by the IOC container. A complete Bean life cycle can refer to the Spring Bean life cycle . Here we mainly record some details related to the Bean life cycle.

Bean initialization and destruction

Throughout the life cycle, we can customize the initialization and destruction hook functions of the Bean. When the Bean's life cycle reaches the corresponding stage, Spring will call our custom Bean initialization and destruction methods. There are many ways to customize Bean initialization and destruction methods, which are introduced one by one below.

@Bean

The previous section introduced that you can @Beanregister the Bean through annotations in the configuration class, and we can also use it to specify the initialization and methods of the Bean.

To demonstrate, we create a new Spring Boot project, and then create a Userclass:

public class User {
    public User() {
        System.out.println("调用无参构造器创建User");
    }
    public void init() {
        System.out.println("初始化User");
    }
    public void destory() {
        System.out.println("销毁User");
    }
}

Then register the component in the configuration class and specify the initialization and destruction methods:

@Configuration
public class WebConfig {

    @Bean(initMethod = "init", destroyMethod = "destory")
    public User user() {
        return new User();
    }
}

Wherein initMethod = "init"and destroyMethod = "destory"with the User class init, destorya corresponding method.

Test in the Spring Boot entry class:

// 返回 IOC 容器,使用注解配置,传入配置类
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(WebConfig.class);
User user = context.getBean(User.class);
// 关闭 IOC 容器
context.close();

Start the project and observe the console output:

From the above output, we can see that before the container is started, the parameterless constructor of the object is called to create the object, then the initialization method is called, and the destruction method is called when the container is closed.

The above situation is for singleton, what if the component is in multiple instances? We change the above component registration configuration to multiple cases, then start the project again, and observe the console output:

The console output is consistent with what we discussed in the previous section, that is, in the multi-case mode, the IOC container will not create an object when it is started, but will call the method to create the object every time it gets it, and the object is created. Then call the initialization method. But after the container is closed, Spring does not call the corresponding destruction method. This is because in the multi-case mode, the container does not manage this component (only responsible for creating this component when you need it), so the container does not The corresponding destruction method will not be called.

InitializingBean&DisposableBean

In addition to specifying the initialization and destruction methods in the above way, Spring also provides us with the interface corresponding to initialization and destruction:

  • InitializingBeanThe interface contains a afterPropertiesSetmethod, we can implement the interface, and then write initialization logic in this method.

  • DisposableBeanThe interface contains a destorymethod, we can implement the interface, and then write the destruction logic in this method.

Create a new class, name it Bird, and implement these two interfaces:

public class Bird implements InitializingBean, DisposableBean {
    public Bird() {
        System.out.println("调用无参构造器创建Bird");
    }

    @Override
    public void destroy() {
        System.out.println("销毁Bird");
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("初始化Bird");
    }
}

Register this component in the configuration class:

@Bean
public Bird bird() {
    return new Bird();
}

Test a wave:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(WebConfig.class);
System.out.println("容器创建完毕");
context.close();

Start the project and observe the console output:

@PostConstruct&@PreDestroy

In addition to the above two ways of specifying initialization and destruction methods, we can also use @PostConstructand @PreDestroyannotation modification methods to specify the corresponding initialization and destruction methods.

Create a new class named Fish:

public class Fish {
    public Fish() {
        System.out.println("调用无参构造器创建Fish");
    }

    @PostConstruct
    public void init() {
        System.out.println("初始化Fish");
    }

    @PreDestroy
    public void destory() {
        System.out.println("销毁Fish");
    }
}

Register this component in the configuration class:

@Bean
public Fish fish(){
    return new Fish();
}

Test a wave:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(WebConfig.class);
System.out.println("容器创建完毕");
context.close();

Start the project and observe the console output:

The effect is the same as the above two methods.

These two annotations are not provided by Spring, but provided by the JSR250 specification.

BeanPostProcessor

Spring provides an BeanPostProcessorinterface, commonly known as the Bean post-notification processor , which provides two methods postProcessBeforeInitializationand postProcessAfterInitialization. Which is postProcessBeforeInitializationexecuted before postProcessAfterInitializationthe initialization method of the component is called, and executed after the initialization method of the component is called. They both contain two input parameters:

  1. bean: current component object;

  2. beanName: The name of the current component in the container.

Both methods return an Object type, we can directly return the current component object, or return after packaging.

Let's define BeanPostProcessorthe implementation class of an interface MyBeanPostProcessor:

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + " 初始化之前调用");
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + " 初始化之后调用");
        return bean;
    }
}

Register the component in the configuration class:

@Bean
public MyBeanPostProcessor myBeanPostProcessor () {
    return new MyBeanPostProcessor();
}

Start the project again and observe the console output:

As you can see, BeanPostProcessor is effective for all components in the IOC container.

 

Guess you like

Origin blog.csdn.net/u014225733/article/details/100836164