上文说到了扫包最终得到了一个BeanDefinition的Map(Map<String, BeanDefinition> beanDefinitionMap),这章说获取单例Bean的步骤和源码,也就是Bean生命周期的后续步骤。
DefaultListableBeanFactory#preInstantiateSingletons() 获取单例Bean
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
// 获取合并后的BeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
// 获取FactoryBean对象
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
// 创建真正的Bean对象(getObject()返回的对象)
getBean(beanName);
}
}
}
else {
// 创建Bean对象
getBean(beanName);
}
}
}
// 所有的非懒加载单例Bean都创建完了后
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}
以上是获取单例Bean的源码我们一步一步剖析其中的核心步骤
合并BeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
在扫描得到BeanDefinition后就可以根据BeanDefinition来创建对象了,但是在Spring存在一种父子关系的Bean
<bean id = "parent" class="com.maxiake.service.Parent" scope = "prototype"/>
<bean id = "child" class="com.maxiake.service.Child"/>
这种在实际使用中呢比较少,上面的Child类的父亲是Parent 所以要继承他的scope属性那么就需要一个父子合并得到一个RootBeanDefinition
加载类
在加载类之前会根据刚刚合并得到的RootBeanDefinition来判断是否是一个接口Bean,是否单例,是否非懒加载,
校验通过呢又回去判断是否实现了FactoryBean接口
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
// 获取FactoryBean对象
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
// 创建真正的Bean对象(getObject()返回的对象)
getBean(beanName);
}
}
}
else {
// 创建Bean对象
getBean(beanName);
}
}
先来说一下什么是FactoryBean
FactoryBean
我们举一个简单的例子来说明
@Component
public class MaxiaKeService implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new UserService();
}
@Override
public Class<?> getObjectType() {
return UserService.class;
}
}
MaxiaKeService实现了FactoryBean重写了他的两个方法
-
T getObejct()
: 返回由FactoryBean创建的bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中实例缓存池中。 -
Class<T> getObjectType()
: 返回FactoryBean创建的 bean的类型。
FactoryBean还有一个方法有默认实现
boolean isSingleton()
:返回有FactoryBean创建的bean的实例的作用域是singleton还是prototype,这里默认返回的是true,也就是默认是singleton bean。
上述代码往Spring容器注入的是MaxiaKeService,当根据BeanName maxiaKeService来找Bean的时候将会得到UserService类型,用&maxiaKeService才能得到MaxiaKeService这个类,看上面源码也能发现在BeanDefinition实现FactoryBaen的时候会走两次getBean 也就是会进行两次Bean的实例化。
加载类
BeanDefinition合并后就可以去创建Bean对象了,而创建Bean就必须实例化对象,实例化就要先加载当前BeanDefinition所对应的class,在AbstractAutowireCapableBeanFactory#createBean()方法中,调用了:
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
这行代码就是去加载类,具体实现:
// 如果beanClass被加载了
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
}
// 如果beanClass没有被加载
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)
() -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
}
else {
return doResolveBeanClass(mbd, typesToMatch);
}
如果beanClass属性是Class那么就直接返回,如果不是则会根据类名进行加载(doResolveBeanClass)
实例化前
加载到类就要执行实例化前的步骤了:
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
Spring提供了一个拓展点,允许开发者来控制实例化对象之前的一些操作,这个拓展点叫: InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()
实现这个接口后重写postProcessBeforeInstantiation()方法的话spring就会在实例化前去执行这个重写的逻辑处理。
推断构造方法
Spring在根据某个类创建Bean的过程中,需要使用构造方法来实例化得到一个对象,但是如果存在多个构造方法spring如何选择?
判断逻辑:
1.如果一个类只有一个构造方法不管是有参无参,spring都会选择该构造方法。
2.如果一个类有多个构造方法,spring会选取无参构造,如果不存在无参构造就会报错。
3.如果在构造方法上加上@Autowired注解,spring就会去选取这个构造去实例化。
实例化
AbstractAutowireCapableBeanFactory#doCreateBean()
// 创建Bean实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
Supplier实例化对象
首先要判断BeanDefinition是否设置了Supplier设置了则使用Supplier来创建对象
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
工厂方法创建对象
如果没有Supplier,则检查是否设置了factoryMethod,也就是工厂方法
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
BeanDefinition后置处理器
在实例化Bean出来后spring又提供了一个拓展点可以对BeanDefinition进行加工处理
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
这个拓展点由MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition()提供
实例化后
在处理完BeanDefinition后,Spring又设计了一个扩展点:
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
属性赋值
populateBean(beanName, mbd, instanceWrapper);
这个步骤中,就会处理@Autowired、@Resource、@Value等注解
执行Aware
完成了属性赋值之后,Spring会执行一些回调,包括:
- BeanNameAware:回传beanName给bean对象。
- BeanClassLoaderAware:回传classLoader给bean对象。
- BeanFactoryAware:回传beanFactory给对象。
初始化前
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
BeanPostProcessor.postProcessBeforeInitialization()这个拓展点实现
利用初始化前,可以对进行了依赖注入的Bean进行处理。
初始化
invokeInitMethods(beanName, wrappedBean, mbd);
- 查看当前Bean对象是否实现了InitializingBean接口,如果实现了就调用其afterPropertiesSet() 方法
- 执行BeanDefinition中指定的初始化方法
初始化后
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
BeanPostProcessor.postProcessAfterInitialization()这个拓展点实现
以在这个步骤中,对Bean最终进行处理,Spring中的AOP就是基于初始化后实现的,初始化后返 回的对象才是最终的Bean对象。
总结BeanPostProcesso
- InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
- 实例化
- MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()
- InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
- 自动注入
- InstantiationAwareBeanPostProcessor.postProcessProperties()
- Aware对象
- BeanPostProcessor.postProcessBeforeInitialization()
- 初始化
- BeanPostProcessor.postProcessAfterInitialization()