19-Spring源码解析之Bean的生命周期(4)——initializeBean

Spring版本:<version>5.2.1.RELEASE</version>

上一篇:18-Spring源码解析之Bean的生命周期(3)——【doCreateBean】和【createBeanInstance】

上一篇我们讲解了doCreateBean方法来创建Bean实例,它首先调用createBeanInstance方法来实例化Bean,其次处理依赖问题,接着对该Bean进行属性赋值(populateBean)方法,再接着对Bean进行初始化工作(initializeBean),本篇文章就看一下Spring是如何帮我们完成Bean的初始化的。

一、initializeBean

还记得在实体类中我们通过实现InitializingBean接口后需要重写afterPropertiesSet方法吗?这个方法的执行时机就是在Bean属性赋值(populateBean)后调用initiali在这里插入代码片zeBean指定的方法来根据用户业务进行相应的实例化。

	protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
//-------------------------------------------------【功能一】--二、 详细介绍----------------------------------------------		
			// 激活Aware方法
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
		
//-------------------------------------------------【功能二】--三、 详细介绍----------------------------------------------		
			// 应用后处理器
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
//-------------------------------------------------【功能三】--四、 详细介绍----------------------------------------------			
			// 激活用户自定义的initMethod或者afterPropertiesSet方法
			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()) {
//-------------------------------------------------【功能四】--五、 详细介绍----------------------------------------------		
			// 应用后处理器
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

从上面可以看出,该方法一共做了四件事情:

  • 【功能一】激活Aware方法
  • 【功能二】应用所有BeanPostProcessorpostProcessBeforeInitialization方法
  • 【功能三】调用用户自定义的initMethod或者afterPropertiesSet方法
  • 【功能四】应用所有BeanPostProcessorpostProcessAfterInitialization方法

下面我们就来依次说一下这几个功能是如何实现的。

二、【功能一】激活Aware方法

在分析这个功能实现的原理之前,我们需要先知道什么是Aware以及它是干什么的。

Spring中提供给了一些Aware接口,比如:

在这里插入图片描述
而实现了对应Aware接口的Bean在实例化之后,可以获取一些相对应的资源,比如:实现了BeanFactoryAware接口的Bean在实例化之后,Spring会给这个Bean注入BeanFactory实例,而实现了ApplicationContextAwareBean,在在实例化之后,Spring会给这个Bean注入ApplicationContextAware实例。我们首先通过示例的方式来了解一下Aware的简单使用。

1.1 Aware的例子

1.1.1 定义普通的Bean

package com.spring.aware;

import org.springframework.stereotype.Component;

@Component
public class Hello {
    public void say() {
        System.out.println("hello");
    }
}

1.1.2 定义BeanFactoryAware的实现类

package com.spring.aware;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.stereotype.Component;

@Component
public class BeanFactoryAwareTest implements BeanFactoryAware {
    private BeanFactory beanFactory;

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

    public void testAware() {
        Hello hello = beanFactory.getBean(Hello.class);
        hello.say();
    }
}

1.1.3 配置类

@Configuration
@ComponentScan("com.spring")
public class MainConfig {

}

1.1.4 测试类

public class Test {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        BeanFactoryAwareTest beanFactoryAwareTest = applicationContext.getBean(BeanFactoryAwareTest.class);
        beanFactoryAwareTest.testAware();
    }
}

1.1.5 测试结果

控制台输出:

hello

首先,我们要意识到一点,Spring中代表容器的beanFactory我们普通类是无法得到的,因为他是一个内部类。如果想要得到,我们需要增加一些操作。
接着,我们分析一下上述例子,Hello类是一个普通类,通过Component注解注册到容器中,BeanFactoryAwareTest类是实现了BeanFactoryAware接口,实现了这个接口后,我们需要实现setBeanFactory方法,而这个方法会在BeanFactoryAwareTest类在创建对应Bean的初始化之前调用,即我们1.节讲到的时候调用。这样,这个BeanFactoryAwareTest类就得到了Spring中代表容器的beanFactory,并且可以根据得到的beanFactory获取容器中所有的Bean

1.2 invokeAwareMethods方法

现在知道了Aware的作用后,我们就可以看看initializeBean中调用invokeAwareMethods方法,这个invokeAwareMethods的具体实现了。

	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);
			}
		}
	}

可以看到,实际上这个代码很简单,就是根据Bean的类型来将对应类型的Bean放到Bean中。

因为刚刚1.1节的例子实现的是BeanFactoryAware接口,所以走到第三个if判断条件的地方,然后调用setBeanFactory方法,这个setBeanFactory方法即我们1.1.2节中的代码:

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

三、【功能二】applyBeanPostProcessorsBeforeInitialization

BeanPostProcessor大家都不陌生,这是Spring开放式架构中一个必不可少的亮点,给用户充足的权限去更改或者扩展Spring,而除了BeanPostProcessor外还有很多其他的PostProcessor,当然大部分都是以此为基础,继承自BeanPostProcessor

而且在前面BeanPostProcessor大家也有接触过,这里就不再详细的介绍了,而且代码很简单。

	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;
	}

四、【功能三】invokeInitMethods

	protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {
			
//-------------------------------------------------【功能一】------------------------------------------------		
		// 判断当前Bean对应的实体类是否实现了InitializingBean接口
		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
			if (logger.isTraceEnabled()) {
				logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
			}
			if (System.getSecurityManager() != null) {
				try {
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					}, getAccessControlContext());
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				// 若实现InitializeBean接口,就执行afterPropertiesSet方法
				((InitializingBean) bean).afterPropertiesSet();
			}
		}
//-------------------------------------------------【功能二】------------------------------------------------
		// 判断当前Bean对应的实体类没有实现InitializingBean接口,但是有initMethod方法,则执行它的initMethod方法			
		if (mbd != null && bean.getClass() != NullBean.class) {
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}

从上面代码可以看出:@Bean(initMethod)afterPropertiesSet都是在Bean时执行的,执行顺序时afterPropertiesSet先执行, @Bean(initMethod)后执行。

五、总结

initializeBean方法主要包含以下四个功能

  • 【功能一】激活Aware方法
  • 【功能二】应用所有BeanPostProcessorpostProcessBeforeInitialization方法
  • 【功能三】调用用户自定义的initMethod或者afterPropertiesSet方法
  • 【功能四】应用所有BeanPostProcessorpostProcessAfterInitialization方法

到本篇结束,Bean的生命周期就剩下DisposableBean没有讲解了。DisposableBean是提供了销毁方法的扩展入口。这个方法很简单,在以后会添加到之前的文章中。

下一篇讲解Spring的一个非常重要的功能!依赖注入!在注解驱动中,就是与@Autowired注解有关的知识。

发布了397 篇原创文章 · 获赞 71 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/xiaojie_570/article/details/104774773