spring源碼解析---spring-core(三)

getBean

  • 這裏即是bean初始化的核心邏輯。源碼比較複雜,分開說。以getBean(String name)爲例。AbstractBeanFactory.getBean:
  • @Overridepublic Object getBean(String name) throws BeansException {

    return doGetBean(name, null, null, false);html

    }java

  • 第二個參數表示bean的Class類型,第三個表示建立bean須要的參數,最後一個表示不須要進行類型檢查。

beanName轉化

  • final String beanName = transformedBeanName(name);
  • 這裏是將FactoryBean的前綴去掉以及將別名轉爲真實的名字。

手動註冊bean檢測

  • 前面註冊環境一節說過,Spring其實手動註冊了一些單例bean。這一步就是檢測是否是這些bean。若是是,那麼再檢測是否是工廠bean,若是是返回其工廠方法返回的實例,若是不是返回bean自己。
  • Object sharedInstance = getSingleton(beanName);

    if (sharedInstance != null && args == null) {git

    bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);github

    }session

檢查父容器

  • 若是父容器存在而且存在此bean定義,那麼交由其父容器初始化:
  • BeanFactory parentBeanFactory = getParentBeanFactory();

    if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {數據結構

    // Not found -> check parent.app

    //此方法實際上是作了前面beanName轉化的逆操做,由於父容器一樣會進行轉化操做ide

    String nameToLookup = originalBeanName(name);post

    if (args != null) {ui

    // 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。
  • 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的初始化,在這裏一次說明了。
  • 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方法

是否存在

  • 首先會檢測是否已經存在,若是存在,直接返回:
  • synchronized (this.singletonObjects) {

    Object singletonObject = this.singletonObjects.get(beanName);

    }

  • 全部的單例bean都保存在這樣的數據結構中:ConcurrentHashMap<String, Object>。

bean建立

  • 源碼位於AbstractAutowireCapableBeanFactory.createBean,主要分爲幾個部分:
lookup-method檢測
  • 此部分用於檢測lookup-method標籤配置的方法是否存在:
  • RootBeanDefinition mbdToUse = mbd;

    mbdToUse.prepareMethodOverrides();

  • prepareMethodOverrides:
  • 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:
  • 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方法。
  • Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

    if (bean != null) {

    return bean;

    }

    Object beanInstance = doCreateBean(beanName, mbdToUse, args);

    return beanInstance;

  • 繼續:
  • 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)
  • 關鍵代碼:
  • BeanWrapper instanceWrapper = null;

    if (instanceWrapper == null) {

    instanceWrapper = createBeanInstance(beanName, mbd, args);

    }

  • createBeanInstance的建立過程又分爲如下幾種狀況:
  • 工廠bean:

    調用instantiateUsingFactoryMethod方法:

    protected BeanWrapper instantiateUsingFactoryMethod(

    String beanName, RootBeanDefinition mbd, Object[] explicitArgs) {

    return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);

    }

    注意,此處的工廠bean指的是配置了factory-bean/factory-method屬性的bean,不是實現了FacrotyBean接口的bean。若是沒有配置factory-bean屬性,那麼factory-method指向的方法必須是靜態的。此方法主要作了這麼幾件事:

  • 初始化一個BeanWrapperImpl對象。
  • 根據設置的參數列表使用反射的方法尋找相應的方法對象。
  • InstantiationStrategy:

    bean的初始化在此處又抽成了策略模式,類圖:

    instantiateUsingFactoryMethod部分源碼:

    beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(

    mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);

    getInstantiationStrategy返回的是CglibSubclassingInstantiationStrategy對象。此處instantiate實現也很簡單,就是調用工廠方法的Method對象反射調用其invoke便可獲得對象,SimpleInstantiationStrategy.

    instantiate核心源碼:

    @Overridepublic Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner,

    Object factoryBean, final Method factoryMethod, Object... args) {

    return factoryMethod.invoke(factoryBean, args);

    }

  • 構造器自動裝配

    createBeanInstance部分源碼:

    // Need to determine the constructor...Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

    if (ctors != null ||

    mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||

    //配置了<constructor-arg>子元素

    mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {

    return autowireConstructor(beanName, mbd, ctors, args);

    }

    determineConstructorsFromBeanPostProcessors源碼:

    protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(Class<?> beanClass, String beanName) {

    if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {

    for (BeanPostProcessor bp : getBeanPostProcessors()) {

    if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {

    SmartInstantiationAwareBeanPostProcessor ibp =

    (SmartInstantiationAwareBeanPostProcessor) bp;

    Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);

    if (ctors != null) {

    return ctors;

    }

    }

    }

    }

    return null;

    }

    可見是由SmartInstantiationAwareBeanPostProcessor決定的,默認是沒有配置這種東西的。

    以後就是判斷bean的自動裝配模式,能夠經過以下方式配置:

    <bean id="student" class="base.Student" primary="true" autowire="default" />

    autowire共有如下幾種選項:

  • no: 默認的,不進行自動裝配。在這種狀況下,只能經過ref方式引用其它bean。
  • byName: 根據bean裏面屬性的名字在BeanFactory中進行查找並裝配。
  • byType: 按類型。
  • constructor: 以byType的方式查找bean的構造參數列表。
  • default: 由父bean決定。
  • 參考:Spring - bean的autowire屬性(自動裝配)
  • autowireConstructor調用的是ConstructorResolver.autowireConstructor,此方法主要作了兩件事:
  • 獲得合適的構造器對象。
  • 根據構造器參數的類型去BeanFactory查找相應的bean:

    入口方法在ConstructorResolver.resolveAutowiredArgument:

    protected Object resolveAutowiredArgument(

    MethodParameter param, String beanName, Set<String> autowiredBeanNames,

    TypeConverter typeConverter) {

    return this.beanFactory.resolveDependency(

    new DependencyDescriptor(param, true), beanName,

    autowiredBeanNames, typeConverter);

    }

  • 最終調用的仍是CglibSubclassingInstantiationStrategy.instantiate方法,關鍵源碼:
  • @Overridepublic Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner,

    final Constructor<?> ctor, Object... args) {

    if (bd.getMethodOverrides().isEmpty()) {

    //反射調用

    return BeanUtils.instantiateClass(ctor, args);

    } else {

    return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);

    }

    }

  • 能夠看出,若是配置了lookup-method標籤,獲得的其實是用Cglib生成的目標類的代理子類。
  • CglibSubclassingInstantiationStrategy.instantiateWithMethodInjection:
  • @Overrideprotected Object instantiateWithMethodInjection(RootBeanDefinition bd, String beanName, BeanFactory owner,Constructor<?> ctor, Object... args) {

    // Must generate CGLIB subclass...

    return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);

    }

  • 默認構造器

    一行代碼,很簡單:

    // No special handling: simply use no-arg constructor.return instantiateBean(beanName, mbd);

MergedBeanDefinitionPostProcessor
  • 觸發源碼:
  • synchronized (mbd.postProcessingLock) {

    if (!mbd.postProcessed) {

    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

    mbd.postProcessed = true;

    }

    }

  • 此接口也是Spring內部使用的,無論它了。
屬性解析
  • 入口方法: AbstractAutowireCapableBeanFactory.populateBean,它的做用是: 根據autowire類型進行autowire by name,by type 或者是直接進行設置,簡略後的源碼:
  • 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源碼:
  • 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方法的操做。相關源碼:
  • // Initialize the bean instance.Object exposedObject = bean;

    try {

    populateBean(beanName, mbd, instanceWrapper);

    if (exposedObject != null) {

    exposedObject = initializeBean(beanName, exposedObject, mbd);

    }

    }

  • initializeBean:
  • 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;

    }

  • 主要的操做步驟一目瞭然。
  • Aware方法觸發:

    咱們的bean有可能實現了一些XXXAware接口,此處就是負責調用它們:

    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) {

    ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());

    }

    if (bean instanceof BeanFactoryAware) {

    ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);

    }

    }

    }

  • BeanPostProcessor觸發,沒什麼好說的
  • 調用init方法:

    在XML配置中,bean能夠有一個init-method屬性來指定初始化時調用的方法。從原理來講,其實就是一個反射調用。不過注意這裏有一個InitializingBean的概念。

    此接口只有一個方法:

    void afterPropertiesSet() throws Exception;

    若是咱們的bean實現了此接口,那麼此方法會首先被調用。此接口的意義在於: 當此bean的全部屬性都被設置(注入)後,給bean一個利用現有屬性從新組織或是檢查屬性的機會。感受和init方法有些衝突,不過此接口在Spring被普遍使用。

getObjectForBeanInstance

  • 位於AbstractBeanFactory,此方法的目的在於若是bean是FactoryBean,那麼返回其工廠方法建立的bean,而不是自身。

Prototype初始化

  • AbstractBeanFactory.doGetBean相關源碼:
  • 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。此部分源碼:
  • 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的實現參考類圖.

本文來源於:宋文超super,專屬平臺有csdn、思否(SegmentFault)、 簡書、 開源中國(oschina),轉載請註明出處。
相關文章
相關標籤/搜索