前言
registerBeanPostProcessors 之后,Spring 要开始准备实例化 Bean。不过在这之前,Spring 初始化了非常多的内部组件。
// 国际化消息组件
initMessageSource();
// Initialize event multicaster for this context.
// 初始化事件监听多路广播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 没有具体实现
onRefresh();
// Check for listener beans and register them.
// 注册监听器
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
这些组件目前不需要话费太大精力去研究,不过要注意一点是在实例化 Bean 前,Spring 留了个扩展方法onRefresh();
给程序员扩展。
finishBeanFactoryInitialization
走到这里,要进入 Spring 的核心。
这个方法技术点过于庞大,Spring 对各个执行步骤都考虑的非常周全,因此这个方法内部看起来非常的复杂,往往看到一个点,需要往后面深入好几层,返回来才明白 Spring 开发者为什么这么做。
所以,对于此方法,需要拆分为好几步去分析。这次只需要知道如何实例化一个普通 bean。
配置一个类
以注解配置的方式配置一个 Bean
Myconfig.java
@Configurable
@ComponentScan("com.Playwi0.bean")
public class MyConfig {
}
A.java
javapackage com.Playwi0.bean;
import org.springframework.stereotype.Component;
@Component
public class A {
public A(){
System.out.println("a");
}
}
就这么个普通的 Bean,来看看 Spring 如何实例化。为了简洁明了,我会删去与本次主体无关代码
preInstantiateSingletons
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 删去代码
......
// Instantiate all remaining (non-lazy-init) singletons.
// 开始实例化 bean
beanFactory.preInstantiateSingletons();
}
跟进此方法 preInstantiateSingletons
@Override
public void preInstantiateSingletons() throws BeansException {
// 删去代码
.....
// 先 copy 一份所有添加到 BeanFactory 的 beanDefinition 的名称
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
// 通过 getMergedLocalBeanDefinition 方法合并所有需要合并的 BeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 要在这一步初始化需要满足三个条件:不是抽象类,BeanDefinition 必须是单例,没有设置延迟加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
// 删去代码
.....
}
else {
getBean(beanName);
}
}
}
// 删去代码
.....
}
遍历所有的 beanDefinition 的名称,调用了getMergedLocalBeanDefinition(beanName);
方法进行 BeanDefinition 之间的合并,这个方法后面文章会细讲,这里只需要知道当前 BeanDefinition 会与父类或接口的 BeanDefinition 某些属性进行整合,得到全新的 RootBeanDefinition。
要想实例化 Bean,还要满足三个要求:不是抽象类,BeanDefinition 必须是单例,没有设置延迟加载。也就是在 Spring 开始的时候,原型类型的 Bean,并不会实例化。
最后判断是不是 FactoryBean,前面配置的肯定不是一个 FactoryBean,因此会进入getBean(beanName);
.
getBean
getBean 也是一个非常重要的方法,同样的,在这里我们只需截取需要的部分就可以,后面还会具体分析。
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
这里面调用的是 doGetBean 方法
doGetBean
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 删除代码
....
// 从缓存找 Bean,如果已经实例化可以找到
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// 删除代码
....
}
else {
// 删除代码
....
// 如果没有实例化 BeanDefinition 则递归循环调用父 BeanFactory,也就是最顶层的 BeanFactory 去实例化 BeanDefinition
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
// 删除代码
....
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 不是抽象类
checkMergedBeanDefinition(mbd, beanName, args);
// 如果有 DependsOn,要先实例化 DependsOn 的 Bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
// 删除代码
....
}
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
// 删除代码
....
}
else if (mbd.isPrototype()) {
// 删除代码
....
}
return (T) bean;
}
Spring 在实例化之前,会检查一遍缓存,如果已经实例化,会从缓存里取出来。
Object sharedInstance = getSingleton(beanName);
我们是第一次进来,正常情况下是没有实例化的,因此会到else
逻辑。
这里的第一步是递归找出父 BeanFactory,有点类似于 Java 的双亲委派机制,采用最顶层的 BeanFactory 去生产 Bean,防止多次加载。正常情况是不会经过这里。
最终走进try
代码块,第一步和前面一样合并 BeanDefinition,再一次检查是不是抽象类,抽象类是不能实例化的。
protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
throws BeanDefinitionStoreException {
if (mbd.isAbstract()) {
throw new BeanIsAbstractException(beanName);
}
}
可能你会问,这里为什么只判断一个条件?注意这里是 getBean 方法进来,这个方法外面也是可以调用的,而前面三个条件,是 Spring 初始化内部的判断。
在这之后,如果该类有依赖的 Bean,要先实例化依赖的 Bean 调用的也是 getBean 方法。很明显前面配置的 Bean 是没有的。
再一次判断是否为单例,单例有单例的实例化方式,原型有原型的。前面并没有配置,默认为单例,进入到 getSingleton 方法,这个方法和上面的并不是同一个方法,同时里面传了个 Lamber 表达式,转换一下,更好阅读一点
public interface ObjectFactory<T> {
T getObject() throws BeansException;
}
ObjectFactory singletonFactory = new ObjectFactory{
public T getObject() throws BeansException{
return createBean(beanName, mbd, args);
}
}
sharedInstance = getSingleton(beanName, singletonFactory);
getSingleton
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 删除代码
....
// 把 Bean 加入到正在创建集合 this.singletonsCurrentlyInCreation.add(beanName)
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
// 删除代码
....
try {
.
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// 删除代码
....
}
catch (BeanCreationException ex) {
// 删除代码
....
}
finally {
// 删除代码
....
afterSingletonCreation(beanName);
}
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
这句代码先留着,后边一并解释。
Object singletonObject = this.singletonObjects.get(beanName);
beforeSingletonCreation(beanName);
这里会把 beanName 放入 singletonsCurrentlyInCreation 集合,表示这个 Bean 在实例化。
protected void beforeSingletonCreation(String beanName) {
// 在这正在实例化 Bean 会被加入到 singletonsCurrentlyInCreation 集合
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
在这行代码singletonObject = singletonFactory.getObject();
执行完后,singletonObject 变量接收的就是实例化好的 Bean。
实例化好后,newSingleton = true;
标记有一个新的 Bean 生成,在最后面使用到了这个变量。
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 放到集合
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
也就是说每个实例化好的 Bean, 都会放到这个集合里面,作为 Spring 的缓存。“从 Spring 容器里取出一个 Bean”,狭义上说的容器就是这个 singletonObjects 集合。看到这里你应该明白,这并不能代表 Spring 容器,只是容器里的一个 Map,专门被用来保存实例化好的 Bean,可以被认作为缓存。因此你会看到,Spring 在前面多次从这个 Map 中取 Bean,其实就是检查这个 Bean 有没有被实例化;如果实例化了,就不需要在走这么复杂的步骤,提高效率。
/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
加入 Map 之前,还有一行代码afterSingletonCreation(beanName);
,在finally
代码块里。
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
这里最重要的一步就是把 beanName 移出了 singletonsCurrentlyInCreation 集合,因为这个 Bean 已经实例化完成。
createBean
singletonObject = singletonFactory.getObject();
这里调用的是前面 Lamber 表达式中的 return createBean(beanName, mbd, args);
这行代码。
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 删除代码
....
RootBeanDefinition mbdToUse = mbd;
// 删除代码
....
try {
// 开始创建 Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// 删除代码
....
}
catch (Throwable ex) {
// 删除代码
....
}
}
跟进 doCreateBean 方法
doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
// 删除代码
....
Object exposedObject = bean;
// 删除代码
....
return exposedObject;
}
如果是单例,则先把缓存中那一份移除。注意 factoryBeanInstanceCache 保存不是 Bean 实例,是包装了 Bean 实例的 BeanWrapper。其实也不算移除,算是取出来,如果存在,说明已经实例化过了,跳过实例化步骤。没有进入实例化instanceWrapper = createBeanInstance(beanName, mbd, args);
createBeanInstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 删除代码
....
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}
前面是推断构造方法的过程,这里的推断构造方法不是想象那样,取出构造方法,后面文章会分析,直接到最后 instantiateBean(beanName, mbd);
instantiateBean
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
getInstantiationStrategy().instantiate(mbd, beanName, parent),
getAccessControlContext());
}
else {
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
不管走进哪个判断,都是执行getInstantiationStrategy().instantiate(mbd, beanName, parent);
instantiate
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
// 删除代码
....
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// 删除代码
....
}
}
这一步是拿到默认构造方法,最明显的一行代码constructorToUse = clazz.getDeclaredConstructor();
instantiateClass
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
// 删除代码
....
return ctor.newInstance(argsWithDefaultValues);
}
}
catch (InstantiationException ex) {
// 删除代码
....
}
}
最后反射执行ctor.newInstance(argsWithDefaultValues);
实例化 Bean。