spring bean生命周期四---Spring Bean 初始化阶段(Initialization)

目录

概述

一、initializeBean

2.1、invokeAwareMethods - 激活 Aware 方法

2.2、Spring Bean 初始化前阶段

第七次调用后置处理器

2.3、 invokeInitMethods - 激活自定义的init方法

2.4、Spring Bean 初始化后阶段

第八次调用后置处理器 postProcessAfterInitialization

三、Spring Bean 初始化完成阶段

四、测试代码案例:


概述

本文是笔者阅读Spring源码的记录文章,由于本人技术水平有限,在文章中难免出现错误,如有发现,感谢各位指正。在阅读过程中也创建了一些衍生文章,衍生文章的意义是因为自己在看源码的过程中,部分知识点并不了解或者对某些知识点产生了兴趣,所以为了更好的阅读源码,所以开设了衍生篇的文章来更好的对这些知识点进行进一步的学习。

这篇文章是 spring bean生命周期二---Spring Bean实例化( Instantiation)阶段 的文章的展开内容。Spring 在 AbstractAutowireCapableBeanFactory#doCreateBean 方法中,完成了bean的完整创建。而在上篇 spring bean生命周期三---Spring Bean populateBean 属性填充阶段 中,完成了Bean的属性注入,表面上看起来 Bean的创建过程已经结束了。实际上还有一些收尾工作没有完成。本文就是完成Bean创建的收尾工作:完成 Aware 接口的功能,调用后处理器的Bean的后置方法,以及指定的init 方法的激活。

本阶段主要包括:激活 Aware 方法、Spring Bean 初始化前阶段、Spring Bean 初始化阶段(Initialization)、Spring Bean 初始化后阶段、Spring Bean 初始化完成阶段。

spring bean生命周期四---Spring Bean 初始化阶段(Initialization)_第1张图片

一、initializeBean初始化阶段

相较于前几篇的内容,本文的内容显得简单了很多。具体代码如下:

下面的代码只要完成了 Spring Bean 初始化前阶段、Spring Bean 初始化阶段(Initialization)、Spring Bean 初始化后阶段

//初始容器创建的Bean实例对象,为其添加BeanPostProcessor后置处理器
	protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		//JDK的安全机制验证权限
		if (System.getSecurityManager() != null) {
			//实现PrivilegedAction接口的匿名内部类
			AccessController.doPrivileged((PrivilegedAction) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			//为Bean实例对象包装相关属性,如名称,类加载器,所属容器等信息
			//todo Spring Bean Aware 接口回调阶段
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		//todo  第七次调用后置处理器 BeanPostProcessor后置处理器的postProcessBeforeInitialization
		//回调方法的调用,为Bean实例初始化前做一些处理
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		//todo 1、先处理了 InitializingBean#afterPropertiesSet()
		// 2、调用Bean实例对象初始化的方法,这个初始化方法是在Spring Bean定义配置
		//文件中通过init-method属性指定的
		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		//todo 第八次调用 BeanPostProcessor后置处理器的postProcessAfterInitialization
		//回调方法的调用,为Bean实例初始化之后做一些处理
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}
 
  

2.1、invokeAwareMethods - 激活 Aware 方法

这个方法很简单,完成了 Aware 接口的激活功能。可以简单的说 :

  • 如果bean实现了BeanNameAware 接口,则将 beanName设值进去
  • 如果bean实现了BeanClassLoaderAware接口,则将 ClassLoader 设值进去
  • 如果bean实现了BeanFactoryAware接口,则将 beanFactory 设值进去
private void invokeAwareMethods(final String beanName, final Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

这里简单解释一下 Aware的作用。从上面的代码可以看到,实现不同类型的 Aware 接口会接受到不同得到初始化数据。


举个例子: 如果bean实现了 BeanFactoryAware 接口,那么他就可以在bean内部获取到beanFacotory。

其实Aware 接口的作用 我在分析 AutowiredAnnotationBeanPostProcessor 后处理器的时候才突然想明白的。 AutowiredAnnotationBeanPostProcessor 中完成了Bean的属性和方法注入,属性要从BeanFactory 的缓存中获取,那么AutowiredAnnotationBeanPostProcessor 如何得到的beanFactory呢? 答案是实现了BeanFactoryAware 接口。这样在 AutowiredAnnotationBeanPostProcessor 初始化的时候就通过
void setBeanFactory(BeanFactory beanFactory) 获取到beanFactory。如下图。AutowiredAnnotationBeanPostProcessor 保存了setBeanFactory 带来的beanFactory,并通过此来从容器中获取需要的bean。
在这里插入图片描述

2.2、Spring Bean 初始化前阶段

这里只要是使用加载处理: BeanPostProcessor#postProcessAfterInitialization的实现类

//todo  第七次调用后置处理器 BeanPostProcessor后置处理器的postProcessBeforeInitialization
//回调方法的调用,为Bean实例初始化前做一些处理
if (mbd == null || !mbd.isSynthetic()) {
   wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

第七次调用后置处理器

@Override
	//调用BeanPostProcessor后置处理器实例对象初始化之前的处理方法
	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {
		Object result = existingBean;
		//遍历容器为所创建的Bean添加的所有BeanPostProcessor后置处理器
		for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
			//调用Bean实例所有的后置处理中的初始化前处理方法,为Bean实例对象在初始化之前做一些自定义的处理操作
			//
			Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

2.3、 invokeInitMethods - 激活自定义的init方法

首先需要注意的是,Bean 的初始化方法除了可以使用 init-method 属性(或者 @Bean(initMethod=''”)),还可以通过实现InitializingBean接口,并且在afterPropertiesSet 方法中实现自己初始化的业务逻辑。

调用顺序则是 afterPropertiesSet 先调用,后面调用 init-method 指定的方法。这一点从下面的代码逻辑就能看到。

	protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {
		// 首先检查是否是InitializingBean,如果是的话则需要调用 afterPropertiesSet 方法。
		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
			if (logger.isTraceEnabled()) {
				logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
			}
			// 调用 afterPropertiesSet  方法
			if (System.getSecurityManager() != null) {
				try {
					AccessController.doPrivileged((PrivilegedExceptionAction) () -> {
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					}, getAccessControlContext());
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				((InitializingBean) bean).afterPropertiesSet();
			}
		}
		
		if (mbd != null && bean.getClass() != NullBean.class) {
			// 从RootBeanDefinition 中获取initMethod 方法名称
			String initMethodName = mbd.getInitMethodName();
			// 调用initMethod 方法。
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}
 
  

2.4、Spring Bean 初始化后阶段

这里只要是使用加载处理: BeanPostProcessor#postProcessAfterInitialization 的实现类

//todo 第八次调用 BeanPostProcessor后置处理器的postProcessAfterInitialization
		//回调方法的调用,为Bean实例初始化之后做一些处理
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

第八次调用后置处理器 postProcessAfterInitialization

@Override
	//调用BeanPostProcessor后置处理器实例对象初始化之后的处理方法
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		//TODO 遍历容器为所创建的Bean添加的所有BeanPostProcessor后置处理器
		for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
			//调用Bean实例所有的后置处理中的初始化后处理方法,为Bean实例对象在
			//初始化之后做一些自定义的处理操作
			Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

三、Spring Bean 初始化完成阶段

主要是回调:SmartInitializingSingleton#afterSingletonsInstantiated

使用场景:实现SmartInitializingSingleton的接口后,当所有单例 bean 都初始化完成以后, Spring的IOC容器会回调该接口的 afterSingletonsInstantiated()方法

主要应用场合就是在所有单例 bean 创建完成之后,可以在该回调中做一些事情,例如:

import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.stereotype.Component;
 
@Component
public class MyRegister implements SmartInitializingSingleton {
 
	private ListableBeanFactory beanFactory;
 
	public MyRegister(ListableBeanFactory beanFactory) {
		this.beanFactory = beanFactory;
	}
 
	@Override
	public void afterSingletonsInstantiated() {
		String[] beanNames = beanFactory.getBeanNamesForType(IPerson.class);
		for (String s : beanNames) {
			System.out.println(s);
		}
	}
 
}

在Spring容器启动时,通过SpringApplication.run()-->SpringApplication.refreshContext()-->SpringApplication.refresh() -->AbstractApplicationContext.refresh(),在这个refresh()函数过程中会调用 finishBeanFactoryInitialization(beanFactory)来提前初始化单例bean,具体方法是调用beanFactory.preInstantiateSingletons(),而这里的beanFactory实例实际为接口 ConfigurableListableBeanFactory 的实现类DefaultListableBeanFactory的实例对象。

查看到DefaultListableBeanFactory.preInstantiateSingletons()的源码如下:

spring bean生命周期四---Spring Bean 初始化阶段(Initialization)_第2张图片

至此 bean对象完成被创建成功。

四、测试代码案例:

下面是创建 UserHolder 初始化已经销毁过程

public class UserHolder implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, EnvironmentAware,
        InitializingBean, SmartInitializingSingleton, DisposableBean {

    private final User user;

    private Integer number;

    private String description;

    private ClassLoader classLoader;

    private BeanFactory beanFactory;

    private String beanName;

    private Environment environment;

    public UserHolder(User user) {
        this.user = user;
    }

    public Integer getNumber() {
        return number;
    }

    public void setNumber(Integer number) {
        this.number = number;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    /*****  下面是 Aware 回调方法*** */
    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
    /*****  =Aware 回调方法 结束*** */
    /**
     * 依赖于注解驱动
     * 当前场景:BeanFactory
     */
    @PostConstruct
    public void initPostConstruct() {
        // postProcessBeforeInitialization V3 -> initPostConstruct V4
        this.description = "The user holder V4";
        System.out.println("initPostConstruct() = " + description);
    }

    /**
     * InitializingBean 的初始化话方法
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        // initPostConstruct V4 -> afterPropertiesSet V5
        this.description = "The user holder V5";
        System.out.println("afterPropertiesSet() = " + description);
    }

    /**
     * 自定义初始化方法
     */
    public void init() {
        // initPostConstruct V5 -> afterPropertiesSet V6
        this.description = "The user holder V6";
        System.out.println("init() = " + description);
    }

    /**
     * 注解中的销毁方法
     */
    @PreDestroy
    public void preDestroy() {
        // postProcessBeforeDestruction : The user holder V9
        this.description = "The user holder V10";
        System.out.println("preDestroy() = " + description);
    }

    /**
     * DisposableBean的销毁方法
     */
    @Override
    public void destroy() throws Exception {
        // preDestroy : The user holder V10
        this.description = "The user holder V11";
        System.out.println("destroy() = " + description);
    }
    /**
     * 自定义销毁方法
     */
    public void doDestroy() {
        // destroy : The user holder V11
        this.description = "The user holder V12";
        System.out.println("doDestroy() = " + description);
    }




    @Override
    public void afterSingletonsInstantiated() {
        // postProcessAfterInitialization V7 -> afterSingletonsInstantiated V8
        this.description = "The user holder V8";
        System.out.println("afterSingletonsInstantiated() = " + description);
    }

    protected void finalize() throws Throwable {
        System.out.println("The UserHolder is finalized...");
    }


    @Override
    public String toString() {
        return "UserHolder{" +
                "user=" + user +
                ", number=" + number +
                ", description='" + description + '\'' +
                ", beanName='" + beanName + '\'' +
                '}';
    }
}
InstantiationAwareBeanPostProcessor的自定义实现:
class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    @Override
    public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
        if (ObjectUtils.nullSafeEquals("superUser", beanName) && SuperUser.class.equals(beanClass)) {
            // 把配置完成 superUser Bean 覆盖
            return new SuperUser();
        }
        return null; // 保持 Spring IoC 容器的实例化操作
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (ObjectUtils.nullSafeEquals("user", beanName) && User.class.equals(bean.getClass())) {
            User user = (User) bean;
            user.setId(2L);
            user.setName("mercyblitz");
            // "user" 对象不允许属性赋值(填入)(配置元信息 -> 属性值)
            return false;
        }
        return true;
    }

    // user 是跳过 Bean 属性赋值(填入)
    // superUser 也是完全跳过 Bean 实例化(Bean 属性赋值(填入))
    // userHolder

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
            throws BeansException {
        // 对 "userHolder" Bean 进行拦截
        if (ObjectUtils.nullSafeEquals("userHolder", beanName) && UserHolder.class.equals(bean.getClass())) {
            // 假设  配置的话,那么在 PropertyValues 就包含一个 PropertyValue(number=1)

            final MutablePropertyValues propertyValues;

            if (pvs instanceof MutablePropertyValues) {
                propertyValues = (MutablePropertyValues) pvs;
            } else {
                propertyValues = new MutablePropertyValues();
            }

            // 等价于 
            propertyValues.addPropertyValue("number", "1");
            // 原始配置 

            // 如果存在 "description" 属性配置的话
            if (propertyValues.contains("description")) {
                // PropertyValue value 是不可变的
//                    PropertyValue propertyValue = propertyValues.getPropertyValue("description");
                propertyValues.removePropertyValue("description");
                propertyValues.addPropertyValue("description", "The user holder V2");
            }

            return propertyValues;
        }
        return null;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (ObjectUtils.nullSafeEquals("userHolder", beanName) && UserHolder.class.equals(bean.getClass())) {
            UserHolder userHolder = (UserHolder) bean;
            // UserHolder description = "The user holder V2"
            userHolder.setDescription("The user holder V3");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (ObjectUtils.nullSafeEquals("userHolder", beanName) && UserHolder.class.equals(bean.getClass())) {
            UserHolder userHolder = (UserHolder) bean;
            // init() = The user holder V6
            // UserHolder description = "The user holder V6"
            userHolder.setDescription("The user holder V7");
        }
        return bean;
    }
}

 

 

 

 

你可能感兴趣的:(spring源码学习)