spring-core 之 getBean

2021-10-09 16:57:09 浏览数 (1)

getBean

这里便是bean初始化的核心逻辑。源码比较复杂,分开说。以getBean(String name)为例。AbstractBeanFactory.getBean:

代码语言:javascript复制
@Override
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

第二个参数表示bean的Class类型,第三个表示创建bean需要的参数,最后一个表示不需要进行类型检查。

beanName转化

代码语言:javascript复制
final String beanName = transformedBeanName(name);

这里是将FactoryBean的前缀去掉以及将别名转为真实的名字。

手动注册bean检测

前面注册环境一节说过,Spring其实手动注册了一些单例bean。这一步就是检测是不是这些bean。如果是,那么再检测是不是工厂bean,如果是返回其工厂方法返回的实例,如果不是返回bean本身。

代码语言:javascript复制
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

检查父容器

如果父容器存在并且存在此bean定义,那么交由其父容器初始化:

代码语言:javascript复制
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    // Not found -> check parent.
    //此方法其实是做了前面beanName转化的逆操作,因为父容器同样会进行转化操作
    String nameToLookup = originalBeanName(name);
    if (args != null) {
        // Delegation to parent with explicit args.
        return (T) parentBeanFactory.getBean(nameToLookup, args);
    } else {
        // No args -> delegate to standard getBean method.
        return parentBeanFactory.getBean(nameToLookup, requiredType);
    }
}

依赖初始化

bean可以由depends-on属性配置依赖的bean。Spring会首先初始化依赖的bean。

代码语言:javascript复制
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
    for (String dependsOnBean : dependsOn) {
         //检测是否存在循环依赖
        if (isDependent(beanName, dependsOnBean)) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
            "Circular depends-on relationship between '"   beanName   "' and '"   dependsOnBean   "'");
        }
        registerDependentBean(dependsOnBean, beanName);
        getBean(dependsOnBean);
    }
}

registerDependentBean进行了依赖关系的注册,这么做的原因是Spring在即进行bean销毁的时候会首先销毁被依赖的bean。依赖关系的保存是通过一个ConcurrentHashMap<String, Set>完成的,key是bean的真实名字。

Singleton初始化

虽然这里大纲是Singleton初始化,但是getBean方法本身是包括所有scope的初始化,在这里一次说明了。

代码语言:javascript复制
if (mbd.isSingleton()) {
    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
        @Override
        public Object getObject() throws BeansException {
            return createBean(beanName, mbd, args);
        }
    });
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

getSingleton方法

是否存在

首先会检测是否已经存在,如果存在,直接返回:

代码语言:javascript复制
synchronized (this.singletonObjects) {
    Object singletonObject = this.singletonObjects.get(beanName);
}

所有的单例bean都保存在这样的数据结构中: ConcurrentHashMap<String, Object>

bean创建

源码位于AbstractAutowireCapableBeanFactory.createBean,主要分为几个部分:

lookup-method检测

此部分用于检测lookup-method标签配置的方法是否存在:

代码语言:javascript复制
RootBeanDefinition mbdToUse = mbd;
mbdToUse.prepareMethodOverrides();

prepareMethodOverrides:

代码语言:javascript复制
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
    // Check that lookup methods exists.
    MethodOverrides methodOverrides = getMethodOverrides();
    if (!methodOverrides.isEmpty()) {
        Set<MethodOverride> overrides = methodOverrides.getOverrides();
        synchronized (overrides) {
            for (MethodOverride mo : overrides) {
                prepareMethodOverride(mo);
            }
        }
    }
}

prepareMethodOverride:

代码语言:javascript复制
protected void prepareMethodOverride(MethodOverride mo)  {
    int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
    if (count == 0) {
        throw new BeanDefinitionValidationException(
                "Invalid method override: no method with name '"   mo.getMethodName()  
                "' on class ["   getBeanClassName()   "]");
    } else if (count == 1) {
        // Mark override as not overloaded, to avoid the overhead of arg type checking.
        mo.setOverloaded(false);
    }
}
InstantiationAwareBeanPostProcessor触发

在这里触发的是其postProcessBeforeInitialization和postProcessAfterInstantiation方法。

代码语言:javascript复制
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
    return bean;
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;

继续:

代码语言:javascript复制
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        // Make sure bean class is actually resolved at this point.
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            Class<?> targetType = determineTargetType(beanName, mbd);
            if (targetType != null) {
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if (bean != null) {
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}

从这里可以看出,如果InstantiationAwareBeanPostProcessor返回的不是空,那么将不会继续执行剩下的Spring初始化流程,此接口用于初始化自定义的bean,主要是在Spring内部使用

doCreateBean

同样分为几部分。

创建(createBeanInstance)

关键代码:

代码语言:javascript复制
BeanWrapper instanceWrapper = null;
if (instanceWrapper == null) {
    instanceWrapper = createBeanInstance(beanName, mbd, args);
}

createBeanInstance的创建过程又分为以下几种情况:

代码语言:javascript复制
instantiateUsingFactoryMethod部分源码:

```java
beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
    mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);
```

getInstantiationStrategy返回的是CglibSubclassingInstantiationStrategy对象。此处instantiate实现也很简单,就是调用工厂方法的Method对象反射调用其invoke即可得到对象,SimpleInstantiationStrategy.

instantiate核心源码:

```java
@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner,
    Object factoryBean, final Method factoryMethod, Object... args) {
    return factoryMethod.invoke(factoryBean, args);
}
```
MergedBeanDefinitionPostProcessor

触发源码:

代码语言:javascript复制
synchronized (mbd.postProcessingLock) {
    if (!mbd.postProcessed) {
        applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
        mbd.postProcessed = true;
    }
}

此接口也是Spring内部使用的,不管它了。

属性解析

入口方法: AbstractAutowireCapableBeanFactory.populateBean,它的作用是: 根据autowire类型进行autowire by name,by type 或者是直接进行设置,简略后的源码:

代码语言:javascript复制
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    //所有<property>的值
    PropertyValues pvs = mbd.getPropertyValues();

    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

        // Add property values based on autowire by name if applicable.
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }

        // Add property values based on autowire by type if applicable.
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }

        pvs = newPvs;
    }
    //设值
    applyPropertyValues(beanName, mbd, bw, pvs);
}

autowireByName源码:

代码语言:javascript复制
protected void autowireByName(
        String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    //返回所有引用(ref="XXX")的bean名称
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
        if (containsBean(propertyName)) {
             //从BeanFactory获取
            Object bean = getBean(propertyName);
            pvs.add(propertyName, bean);
            registerDependentBean(propertyName, beanName);
        }
    }
}

autowireByType也是同样的套路,所以可以得出结论: autowireByName和autowireByType方法只是先获取到引用的bean,真正的设值是在applyPropertyValues中进行的。

属性设置

Spring判断一个属性可不可以被设置(存不存在)是通过java bean的内省操作来完成的,也就是说,属性可以被设置的条件是此属性拥有public的setter方法,并且注入时的属性名应该是setter的名字

初始化

此处的初始化指的是bean已经构造完成,执行诸如调用其init方法的操作。相关源码:

代码语言:javascript复制
// Initialize the bean instance.
Object exposedObject = bean;
try {
    populateBean(beanName, mbd, instanceWrapper);
    if (exposedObject != null) {
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
}

initializeBean:

代码语言:javascript复制
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
            @Override
            public Object run() {
                invokeAwareMethods(beanName, bean);
                return null;
            }
        }, getAccessControlContext());
    }
    else {
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    invokeInitMethods(beanName, wrappedBean, mbd);

    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

主要的操作步骤一目了然。

getObjectForBeanInstance

位于AbstractBeanFactory,此方法的目的在于如果bean是FactoryBean,那么返回其工厂方法创建的bean,而不是自身。

Prototype初始化

AbstractBeanFactory.doGetBean相关源码:

代码语言:javascript复制
else if (mbd.isPrototype()) {
    // It's a prototype -> create a new instance.
    Object prototypeInstance = null;
    try {
        beforePrototypeCreation(beanName);
        prototypeInstance = createBean(beanName, mbd, args);
    }
    finally {
        afterPrototypeCreation(beanName);
    }
    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

beforePrototypeCreation

此方法用于确保在同一时刻只能有一个此bean在初始化。

createBean

和单例的是一样的,不在赘述。

afterPrototypeCreation

和beforePrototypeCreation对应的,你懂的。

总结

可以看出,初始化其实和单例是一样的,只不过单例多了一个是否已经存在的检查。

其它Scope初始化

其它就指的是request、session。此部分源码:

代码语言:javascript复制
else {
    String scopeName = mbd.getScope();
    final Scope scope = this.scopes.get(scopeName);
    if (scope == null) {
        throw new IllegalStateException("No Scope registered for scope name '"   scopeName   "'");
    }
    Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
        @Override
        public Object getObject() throws BeansException {
            beforePrototypeCreation(beanName);
            try {
                return createBean(beanName, mbd, args);
            }
            finally {
                afterPrototypeCreation(beanName);
            }
        }
    });
    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}

scopes是一个LinkedHashMap<String, Scope>,可以调用 ConfigurableBeanFactory定义的registerScope方法注册其值。

Scope接口继承体系:

根据socpe.get的注释,此方法如果找到了叫做beanName的bean,那么返回,如果没有,将调用ObjectFactory创建之。Scope的实现参考类图。

0 人点赞