Spring注解开发02--------bean的生命周期

概述

什么是bean的生命周期?

bean的生命周期是指一个bean,从创建,再到初始化,最后到销毁的过程!

  1. 构造(对象创建):
    • 单实例,默认容器启动时创建对象
    • 多实例,在每次获取的时候创建对象
  2. 初始化:
    • 对象创建完毕并赋值好,调用初始化方法。
  3. 销毁:
    • 单实例,在容器关闭时调用销毁方法
    • 多实例,创建之后容器就不会管理这个bean了,容器不会调用销毁方法。
  4. 我们还可以通过BeanPostProcessor来进行初始化方法前后的一些操作!

在Spring中是容器来管理bean的生命周期,但是我们可以使用一些我们自定义的方法,来使得容器进行到当前bean的生命周期时来调用我们自定义的初始化与销毁方法。

Spring实现生命周期的几种方式

  1. @Bean方式
    • 指定init-method=""与destroy-method=""
  2. 通过让bean实现InitializingBean(定义初始化逻辑)与DisposableBean(定义销毁逻辑)接口
  3. 使用JSR250提供的两个注解:
    • @PostConstruct: 在bean创建完成并且属性赋值完成,来执行初始化
    • @PreDestroy: 在容器销毁bean之前通知我们清理工作
  4. 通过BeanPostProcessor:
    • 在bean初始化前后进行一些处理工作
    • postProcessBeforeInitialization:在任意初始化调用之前(包括我们指定任意初始化方法之前)
    • postProcessAfterInitialization:在任意初始化方法调用之后

@Bean方式实现

概述

@Bean注解为我们提供了两个属性initMethod与destroyMethod,我们使用使用时最直接赋值方法名即可。

测试

1.编写实体类person,编写构造方法,init(初始化方法)与destory(销毁方法)

package com.xdw.pojo;


public class Person {

    private Integer age;

    private String name;

    public void init() {
        System.out.println("person init。。。");
    }

    public void destory() {
        System.out.println("person destory。。。");
    }

    public Person() {
    }

    public Person(Integer age, String name) {
        this.age = age;
        this.name = name;
        System.out.println("person constructor。。。");
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }


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

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

2.在配置类中编写我们创建bean的方法,并使用@Bean注解,设置initMethod与destoryMethod分别指向我们刚刚创建的初始化与销毁方法。

package com.xdw.config;

import com.xdw.pojo.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MainConfigOfLifeCycle {

    @Bean(initMethod = "init", destroyMethod = "destory")
    public Person person() {
        return new Person(12, "张三");
    }

}

3.编写测试类方法

@Test
public void test01() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
    // 单例模式,在容器关闭时会自动销毁bean
    applicationContext.close();
}

4.运行,测试结果如下:
Spring注解开发02--------bean的生命周期

可以发现我们指定的初始化与销毁方法被成功调用了。

总结

该种方法实现比较简单,只需要给bean设定初始化与销毁方法,再将方法名分别赋值给@Bean的initMethod与destroyMethod属性。

方式二:通过让bean实现InitializingBean(定义初始化逻辑)与DisposableBean(定义销毁逻辑)接口

概述

该种方式,需要我们创建的bean实现InitializingBean与DisposableBean接口,分别重写afterPropertiesSet与destroy方法。

测试

1.新增一个Car类,实现InitializingBean与DisposableBean接口

package com.xdw.pojo;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class Car implements InitializingBean, DisposableBean {

    public Car() {
        System.out.println("car constructor......");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("Car destory ......");
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("car afterPropertiesSet......");
    }
}

2.在配置类中编写注入方法

@Bean
public Car car() {
    return new Car();
}

3.测试方法如下:

@Test
public void test01() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
    applicationContext.close();
}

4.运行,测试结果如下:
Spring注解开发02--------bean的生命周期

我们重写的afterPropertiesSet与destroy方法被成功调用。

总结

该种方式需要我们创建的bean实现InitializingBean与DisposableBean接口,并分别重写afterPropertiesSet与destroy方法。

方式三:JSR250提供的两个注解,@PostConstruct`与`@PreDestroy

概述

这位两个注解是java提供的注解,Spring也支持。

测试

1.新增一个Dog类,编写构造方法,初始化方法,与销毁方法

package com.xdw.pojo;


import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class Dog {

    public Dog() {
        System.out.println("dog constructor 。。。。。。");
    }

    @PostConstruct
    public void init() {
        System.out.println("dog @PostConstruct 。。。。。。");
    }

    @PreDestroy
    public void destory() {
        System.out.println("dog @PreDestroy 。。。。。。");
    }
}

2.在配置类中编写bean创建方法

@Bean
public Dog dog() {
    return new Dog();
}

3.编写测试类

import com.xdw.config.MainConfigOfLifeCycle;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestLifeCycle {

    @Test
    public void test01() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
        applicationContext.close();
    }

}

4.运行结果,测试
Spring注解开发02--------bean的生命周期

可以发现,我们使用的@PostConstruct@PreDestroy修饰的方法成功执行。

总结

  • @PostConstruct@PreDestroy这两个注解是java提供的注解
  • @PostConstruct 表示在构造方法之后执行
  • @PreDestroy 表示在实例销毁之前执行

方式四:BeanPostProcessor bean后置处理器

概述

  • BeanPostProcessor可以在bean初始化前后进行一些操作,不会在销毁bean时进行操作。
  • postProcessBeforeInitialization:在任意初始化调用之前(包括我们指定任意初始化方法)
  • postProcessAfterInitialization:在任意初始化方法调用之后(包括我们指定任意初始化方法)

测试

1.新增MyBeanPostProcessor类实现BeanPostProcessor接口

package com.xdw.pojo;

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

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {



    // 任意初始化方法调用之前
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization >=" + beanName + ">=" + bean);
        return bean;
    }

    // 任意初始化方法调用之后
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization >=" + beanName + ">=" + bean);
        return bean;
    }
}

2.在配置类上添加@ComponentScan注解,使得我们新建的MyBeanPostProcessor 注解生效

package com.xdw.config;

import com.xdw.pojo.Dog;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.xdw.beanPostProcessor")
public class MainConfigOfLifeCycle {

    @Bean
    public Dog dog() {
        return new Dog();
    }

}

3.测试方法入下:

@Test
public void test01() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
    applicationContext.close();
}

4.运行测试
Spring注解开发02--------bean的生命周期

我们发现postProcessBeforeInitialization方法与postProcessAfterInitialization分别在初始化方法执行前后被调用。

BeanPostProcessor执行原理

BeanPostProcessor执行原理:
   populateBean(beanName, mbd, instanceWrapper);  // 给bean进行赋值
   initializeBean(beanName, exposedObject, mbd) {
     applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
     invokeInitMethods(beanName, wrappedBean, mbd); // 执行初始化
     applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }

applyBeanPostProcessorsBeforeInitialization源码如下:

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
}

applyBeanPostProcessorsBeforeInitialization方法会遍历得到容器中所有的BeanPostProcessor;挨个执行BeforeInitialization,一旦返回null,跳出for循环,不会执行后面的BeanPostProcessor

总结

  • 在bean初始化方法前后进行一些操作,包括我们自定义的一些初始化方法
  • Spring底层使用了大量的BeanPostProcessor,bean赋值、注入其他组件、@Autowried、生命周期功能注解、@Async等都是通过BeanPostProcessor实现的
上一篇:python 字典转json


下一篇:flink启动报错:java.lang.NoSuchMethodError: org.apache.flink.api.java.ClosureCleaner.clean(Ljava/lang/Obj