spring中bean的生命周期和后处理器

一、综述

本文使用的spring版本是 5.2.12

spring中bean的生命周期从总体上看有以下这几个阶段

实例化,

属性填充(依赖注入)

Aware接口执行

初始化

销毁

然后spring提供了许多bean后处理器,通过这些后处理器可以在以上这些阶段的执行前后进行干预。

二、bean后处理器

spring中的bean后处理器其实就是sring提前定义好的一些接口,使用的时候提供对应的实现,spring就会帮我们执行。

2.1 bean后处理器接口的介绍

2.1.1 BeanPostProcessor (干预初始化前和初始化后)

首先这是一个接口,其中定义了两个方法,分别会在初始化前,初始化后这两个时机执行,对bean的生命周期进行扩展,这两个方法中已经可以拿到半成品bean对象,并且属性填充已经结束了,可以用来对bean中的一些属性进行校验或者重新赋值。

public interface BeanPostProcessor {

	
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

要注意的是这个接口是bean后处理器的顶层接口,其他的后处理器都是它的直接或间接子接口。

2.1.2 InstantiationAwareBeanPostProcessor (实例化前后,属性填充)

这个接口是上边BeanPostProcessor接口的子接口,除了父接口提供的方法外,还多提供了几个方法用来干预

实例化前,实例化后,属性填充,还有一个已经废弃的方法。

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

	
	@Nullable
	default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		return null;
	}

	
	default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        //这个方法如果返回false,生命周期后边的属性填充等就会被跳过
		return true;
	}

	
	@Nullable
	default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
			throws BeansException {
		// 这个方法可以用来对bean进行属性填充
		return null;
	}

    
	@Deprecated
	@Nullable
	default PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

		return pvs;
	}

}

2.1.3DestructionAwareBeanPostProcessor (销毁前)

这个接口也是BeanPostProcessor接口的子接口,其中提供了的方法postProcessBeforeDestruction,

会在bean销毁前执行。

public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {

	// 销毁前执行
	void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;

	// 针对当前的bean return true上边的销毁前方法会被使用,返回false就不会执行
	default boolean requiresDestruction(Object bean) {
		return true;
	}

}

2.2 bean后处理器的使用

上边介绍了bean后处理器接口,下面来介绍下bean后处理器如何使用。

对于ApplicationContext类型的spring容器,后处理器的使用很简单,创建后处理器接口的实现类,然后注册到spring容器中,然后再执行容器的refresh方法,spring就会帮我们执行后处理器的各种方法。

下面来做一个简单的演示。

2.2.1 定义bean后处理器

这里创建一个后处理器,同时实现DestructionAwareBeanPostProcessorInstantiationAwareBeanPostProcessor接口,就可以同时演示上边提到的全部方法

要注意的是,bean后处理器在每个bean的生命周期中都会被执行到,所以需要针对被干预的bean做一些条件判断,像下边就判断了bean1的名称


public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if("bean1".equals(beanName)){
            System.out.println("实例化前方法执行");
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if("bean1".equals(beanName)){
            System.out.println("实例化后方法执行");
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if("bean1".equals(beanName)){
            System.out.println("属性填充方法执行");
        }
        return null;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if("bean1".equals(beanName)){
            System.out.println("初始化前方法执行");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if("bean1".equals(beanName)){
            System.out.println("初始化后方法执行");
        }
        return bean;
    }

    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        if("bean1".equals(beanName)){
            System.out.println("销毁前方法执行");
        }
    }
}

2.2.2bean后处理器的使用

首先先创建一个简单的bean

public class Bean1 {
    public Bean1() {
        System.out.println("---实例化 bean1---");
    }
}

为了演示方便,我们使用一个纯净的ApplicationContext容器的实现类GenericApplicationContext

这个实现类中没有添加spring自带的一些后处理器,方便我们观察结果。

public class LifecycleTest {

    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("bean1",Bean1.class);
        //注册自定义的bean后处理器
        context.registerBean(MyBeanPostProcessor.class);
        context.refresh();
        //关闭容器,调用销毁方法
        context.close();
    }
}

运行上边的代码,控制台会输出如下结果

实例化前方法执行
---实例化 bean1---
实例化后方法执行
属性填充方法执行
初始化前方法执行
初始化后方法执行
销毁前方法执行

符合上边的预期顺序,spring就是通过这样的方式来对bean的创建过程进行干预。

如果在MyBeanPostProcessor的最后增加一个方法requiresDestruction,返回false

@Override
    public boolean requiresDestruction(Object bean) {
        return false;
    }

销毁前方法就不会被执行了。

2.3 spring中常见的bean后处理器介绍

上边介绍了bean后处理器接口和如何使用后处理器,接下来看下spring中提供的一些常见的后处理。

2.3.1 AutowiredAnnotationBeanPostProcessor

这个后处理器用来解析@Autowired注解和@Value注解

public class Bean2 {

    @Autowired
    private Bean1 bean1;

    public Bean1 getBean1() {
        return bean1;
    }
}

先不添加任务后处理器,

public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("bean1",Bean1.class);
        context.registerBean("bean2",Bean2.class);
        context.refresh();
        System.out.println(context.getBean(Bean2.class).getBean1());
}

最终的输出结果中bean2中的属性bean1是null,需要添加后处理器来对 @Autowired注解进行解析。

public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("bean1",Bean1.class);
        context.registerBean("bean2",Bean2.class);
        // 添加后处理器 AutowiredAnnotationBeanPostProcessor
        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
        context.refresh();
        System.out.println(context.getBean(Bean2.class).getBean1());
}

这样bean2中的属性bean1就有值了。

这个后处理是在postProcessProperties(属性填充)方法中对此注解进行解析的。

2.3.2 CommonAnnotationBeanPostProcessor

这个后处理器用来解析@PostConstruct @PreDestroy @Resource注解

这三个注解在CommonAnnotationBeanPostProcessor的不同方法中被解析

其中 @PostConstruct 注解在初始化前方法中被解析,也就是 postProcessBeforeInitialization方法

@PreDestroy 注解在销毁前方法中被解析,也就是postProcessBeforeDestruction方法

@Resource注解 在属性填充方法中被解析,也就是 postProcessProperties方法中

三、Aware接口

spring提供了几个Aware接口,BeanNameAware,BeanClassLoaderAware,BeanFactoryAware

如果一个bean实现了这几个接口,就会在初始化前方法执行之前先执行这几个aware接口中的方法

3.1 BeanNameAware


public interface BeanNameAware extends Aware {

	// name:当前正在创建的bean在beanfactory中的名称
	void setBeanName(String name);

}

如果一个bean实现了这个接口,在执行初始化前方法之前就会先执行bean中的setBeanName方法

public class Bean4 implements BeanNameAware {
    @Override
    public void setBeanName(String name) {
        System.out.println("当前bean的名称是:"+name);
    }
}

public class LifecycleTest {

    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("bean4",Bean4.class);
        context.refresh();
    }
}

所以这个接口用来在bean内部拿到bean名称。

3.2 BeanClassLoaderAware

这个接口用来在bean内部拿到类加载器

3.3 BeanFactoryAware

这个接口用来在bean内部拿到容器对象 BeanFactory,接口内部也是只有一个setBeanFactory方法,可以通过这个方法把beanFactory设置给bean的属性。

以上这几个aware接口都会在初始化前方法执行之前执行。

四、bean初始化接口 InitializingBean

这个接口中提供了一个afterPropertiesSet方法,如何某个Bean实现了这个接口

这个方法会在初始化阶段被执行。

public class Bean3 implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("初始化阶段执行此方法");
    }
}