Spring源碼知識概覽

Spring知識總覽

1.1 IOC

IOC是控制反轉,是一種思想

DI是依賴注入,是控制翻轉的一種實現

Spring的IOC容器是用來存放對象(bean)的,Spring傳統的xml配置方式,容器的大致加載過程為:

  • 1、加載xml配置文件

  • 2、解析xml文件(BeanDefinitionReder接口的xml解析的實現類)

  • 3、封裝BeanDefinition(對xml或者其他配置文件進行解析,拿到bean的組成信息,例如名稱,方法,屬性等)

  • 4、實例化配置文件中註冊的bean(通過反射,通過bean定義的scop屬性值例如singleton-默認方式單例,rototype,request,session,確定bean的存在方式,但是Spring中並不是直接實例化,而是通過第5點的Bean工程來管理,從而達到可擴展的目的,保證可擴展,Spring做了很多工作,這部分比較重要)

  • 5、bean存在容器中(通過反射。BeanFactory是容器根接口,AbtsratAutowireCapableBeanFactory繼承自BeanFactory,DafaultListableBeanFactory繼承自AbstratAutowireCapableBeanFactory。這三個類在Spring中大量出現和使用)

Spring的Bean工廠類圖

從反射到bean容器,為了保證擴展性,需要做很多增強處理,增強處理的接口是BeanFactoryPostProcessor和BeanPostProcessor,這兩個接口有大量的實現。PostProcessor命名常被稱作增強器。可以理解為BeanPostProcessor是為了對bean信息進行增強和修改,BeanFactoryPostProcessor是對beanDefibition進行增強和修改。BeanPostProcessor有兩個方法,一個前置處理方法,一個後置處理方法

例如PlaceholderConfigurerSupport的父類PropertyResourceConfigurer實現了BeanFactoryPostProcessor。那麼PlaceholderConfigurerSupport可以動態修改bean的定義信息

(1)面試題:能詳細描述下bean的生命周期么?(重要)

BeanFactor接口定義了Bean生命周期先後順序,解釋如下:

 * <p>Bean factory implementations should support the standard bean lifecycle interfaces
 * as far as possible. The full set of initialization methods and their standard order is:
 * <ol>
 * <li>BeanNameAware's {@code setBeanName}
 * <li>BeanClassLoaderAware's {@code setBeanClassLoader}
 * <li>BeanFactoryAware's {@code setBeanFactory}
 * <li>EnvironmentAware's {@code setEnvironment}
 * <li>EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
 * <li>ResourceLoaderAware's {@code setResourceLoader}
 * (only applicable when running in an application context)
 * <li>ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
 * (only applicable when running in an application context)
 * <li>MessageSourceAware's {@code setMessageSource}
 * (only applicable when running in an application context)
 * <li>ApplicationContextAware's {@code setApplicationContext}
 * (only applicable when running in an application context)
 * <li>ServletContextAware's {@code setServletContext}
 * (only applicable when running in a web application context)
 * <li>{@code postProcessBeforeInitialization} methods of BeanPostProcessors
 * <li>InitializingBean's {@code afterPropertiesSet}
 * <li>a custom init-method definition
 * <li>{@code postProcessAfterInitialization} methods of BeanPostProcessors
 * </ol>

(2)面試題:Aware接口到底有什麼作用?

通過一種回調的方式,可以拿到Spring的各種組件。比如我創建的A對象,原來只能拿到A對象拿到A對象相應的信息,但是我想通過A對象,拿到Spring容器的其他各種對象,那麼可以藉助這個借口實現。

Aware借口介紹如下,Aere有很多實現類和實現接口。

package org.springframework.beans.factory;

/**
 * A marker superinterface indicating that a bean is eligible to be notified by the
 * Spring container of a particular framework object through a callback-style method.
 * The actual method signature is determined by individual subinterfaces but should
 * typically consist of just one void-returning method that accepts a single argument.
 *
 * <p>Note that merely implementing {@link Aware} provides no default functionality.
 * Rather, processing must be done explicitly, for example in a
 * {@link org.springframework.beans.factory.config.BeanPostProcessor}.
 * Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}
 * for an example of processing specific {@code *Aware} interface callbacks.
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @since 3.1
 */
public interface Aware {

}

例如我們想通過我們創建的A對象拿到beanName。那麼我們可以在A的實體類上實現BeanAware接口,實現接口方法,在我們實例化A對象後,我們可以通過A實例,拿到beanNanem

import org.springframework.beans.factory.BeanNameAware;

public class A implements BeanNameAware {
    
    
    private String beanName;
    
    
    @Override
    public void setBeanName(String name) {
        this.beanName = name;
    }
    
    public String getBeanName() {
        return beanName;
    }
    
}

  • 6、我們可以通過容器的對象get我們想要的bean

容器底層是用map結構來支持的,所以我們可以通過容器get出我們想要的對象bean。Spring中大致存在(String,Object),(Class, Object),(String, ObjectFactory),(String,BeanDefinition)幾種類型的map

(3)面試題:Spring內置對象和Spring普通對象有什麼區別?

內置對象是Spring提前初始化的,是容器需要的對象,比如beanFactory等,並不是我們通過配置文件註冊的bean。Spring普通對象是我們通過xml或者配置類註冊進Spring容器的我們需要的對象。

(4)面試題:BeanFactory和FactorBean的區別?

  • 都是用來創建對象的
  • 當使用BeanFactory創建對象時,必須遵循完整的創建過程,這個過程是由Spring來管理控制的
  • 而使用FactoryBean來創建bean,只需要調用getObject就可以返回具體對象。整個對象的創建過程是由用戶自己來控制的,更加靈活。不主動調用getObject,該對象並未提前創建。不遵循Bean的生命周期
import com.dtsre.dashboard.Student;
import org.springframework.beans.factory.FactoryBean;

public class StudentFactoryBeanTest implements FactoryBean<Student> {
    @Override
    public Student getObject() throws Exception {
        return new Student();
    }

    @Override
    public Class<?> getObjectType() {
        return Student.class;
    }
}

把該FactoryBean的實例StudentFactoryBeanTest註冊到Spring容器中,之後通過拿到容器context,拿到StudentFactoryBeanTest(getBean(StudentFactoryBeanTest)),只有geeBean操作後,Student對象才會被創建

1.2 Spring中重要接口概覽

Spring重要接口概覽