Spring源码之bean的初始化initializeBean方法解读

目录

  • 1. 前言
  • 2. `initializeBean()` 方法概览
  • 3. `initializeBean()` 方法详解
    • 3.1. `invokeAwareMethods()` 方法
    • 3.2. `applyBeanPostProcessorsBeforeInitialization()` 方法(重点
    • 3.3. `invokeInitMethods()` 方法(重点
    • 3.4. `applyBeanPostProcessorsAfterInitialization()` 方法(重点
  • 4. `Spring` 中初始化 `bean` 的方式
    • 4.1. 使用 `@PostConstruct` 注解
    • 4.2. 实现 `InitializingBean` 接口
    • 4.3. 使用 `@Bean` 注解
    • 4.4. 执行顺序

1. 前言

这篇文章是 IOC 容器初始化启动时,抽象类 AbstractAutowireCapableBeanFactorydoCreateBean() 方法里面的 initializeBean() 方法,它是进行 bean 的初始化的方法

阅读本篇文章,同时可以参考阅读 spring源码之getBean(获取 bean)方法解读(二) 和 Spring Aop代理对象的产生(一) 这两篇文章的 doCreateBean() 方法

2. initializeBean() 方法概览

到此时,bean 已完成了如下两个重要工作

  • 调用 createBeanInstance() 方法:完成 bean 的实例化工作
  • 调用 populateBean() 方法:完成 bean 的属性填充注入工作
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
	// 对特殊的bean进行处理:实现了 Aware、BeanClassLoaderAware、BeanFactoryAware 的处理
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			// 激活 Aware 方法
			invokeAwareMethods(beanName, bean);
			return null;
		}, getAccessControlContext());
	}
	else {
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
		// 调用了bean后处理器的方法
		// BeanPostProcessor 提供的方法,在bean初始化前调用,这时的 bean已完成了实例化和属性填充注入工作
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}

	try {
		// 激活自定义的init的方法
		invokeInitMethods(beanName, wrappedBean, mbd);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				(mbd != null ? mbd.getResourceDescription() : null),
				beanName, "Invocation of init method failed", ex);
	}
	if (mbd == null || !mbd.isSynthetic()) {
		// 调用bean后处理器的方法
		// BeanPostProcessor 提供的方法,在bean初始化后调用,这时候的bean 已经创建完成了
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}
	return wrappedBean;
}
  • 对实现了 Aware 接口的 bean 进行相关设置
  • 调用 bean 后处理器的方法 applyBeanPostProcessorsBeforeInitialization()
  • 执行实现了 InitializingBean 或者用户自定义的 init 方法方法
  • 调用 bean 后处理器的方法 applyBeanPostProcessorsAfterInitialization():此处可以产生 aop 的代理对象

3. initializeBean() 方法详解

3.1. invokeAwareMethods() 方法

实现 Aware 接口用于让 bean 能拥有某些额外的感知能力

  • 如果 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);
		}
	}
}

3.2. applyBeanPostProcessorsBeforeInitialization() 方法(重点

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

	Object result = existingBean;
	// 获取所有实现了 BeanPostProcessors 接口的类,进行遍历
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		// 核心方法:postProcessBeforeInitialization()
		Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

postProcessBeforeInitialization() 方法是 BeanPostProcessor 接口提供的方法,可以看到它是在 bean 初始化之前调用的,这时的 bean 已完成了实例化和属性填充注入工作

public interface BeanPostProcessor {

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

	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
}
  • postProcessBeforeInitialization():在 bean 初始化之前调用,可以改变 bean 的一些属性
  • postProcessAfterInitialization():在 bean 初始化之后调用,可以改变 bean 的一些属性

关于 BeanPostProcessor 接口的详解可以查看:https://blog.csdn.net/qq_36882793/article/details/106040809

关于 BeanPostProcessor 接口的详细使用可以查看:https://blog.csdn.net/mamamalululu00000000/article/details/106547490

3.3. invokeInitMethods() 方法(重点

bean 的初始化方式除了可以在 xml 文件中配置 init-method 标签或使用注解@Bean(initMethod=" "),还可以通过实现 InitializingBean 接口,并且在 afterPropertiesSet() 方法中实现自己初始化的业务逻辑

调用顺序则是 afterPropertiesSet() 先调用,后面调用 init-method 指定的方法

Spring源码之bean的初始化initializeBean方法解读_第1张图片

  • Springbean 提供了两种初始化的方式,第一种是实现 InitializingBean 接口

    • 第二种是在 xml 配置文件 init-method 标签来指定
    • 第二种是在 @Bean 注解中通过 initMethod 属性来指定

两种方式可以同时使用。同时使用先调用 afterPropertiesSet() 方法,后执行 init-method 指定的方法

  • 实现 InitializingBean 接口是直接调用 afterPropertiesSet() 方法,与通过反射调用 init-method 指定的方法相比,效率相对来说要高点。但是 init-method 方式消除了对 Spring 的依赖
  • 如果调用 afterPropertiesSet() 方法时出错,那么就不会调用 init-method 指定的方法了

3.4. applyBeanPostProcessorsAfterInitialization() 方法(重点

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

	Object result = existingBean;
	// 获取所有实现了 BeanPostProcessors 接口的类,进行遍历
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		// 核心方法:postProcessAfterInitialization()
		Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

postProcessAfterInitialization() 方法是 BeanPostProcessor 接口提供的方法,可以看到它是在 bean 初始化之后调用的,这时的 bean 已完成了实例化,属性填充注入,初始化的工作;可以认为是一个完整的 bean 已在 spring 容器中了

如果使用了 spring aop 功能,那么代理对象的产生就在这个 applyBeanPostProcessorsAfterInitialization() 方法中。注意产生代理对象的时机

  • 是在 bean 的实例化 createBeanInstance() 方法,属性填充注入populateBean() 方法之后的 initializeBean() 初始化方法中产生的
  • initializeBean() 方法中的applyBeanPostProcessorsAfterInitialization() 方法具体产生

4. Spring 中初始化 bean 的方式

  • xml 配置文件中指定 init-method 标签
  • 使用 @PostConstruct 注解
  • 实现 InitializingBean 接口
  • 使用 @Bean 注解指定

4.1. 使用 @PostConstruct 注解

@Service
public class AService {

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

4.2. 实现 InitializingBean 接口

@Service
public class BService implements InitializingBean {

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

4.3. 使用 @Bean 注解

使用 initMethod() 可以指定初始化方法

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {

	@AliasFor("name")
	String[] value() default {};

	@AliasFor("value")
	String[] name() default {};

	Autowire autowire() default Autowire.NO;

	String initMethod() default "";

	String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
}

4.4. 执行顺序

具体的执行顺序可以查看 initializeBean() 源码
Spring源码之bean的初始化initializeBean方法解读_第2张图片

你可能感兴趣的:(#,源码,spring,spring)