Spring5.x 源碼分析 (一) : 從容器啓動開始

一、從容器開始

最簡單的啓動spring的代碼以下:java

import com.ld.test.config.AppConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestDemo {
  public static void main(String[] args) {
      AnnotationConfigApplicationContext acac = new AnnotationConfigApplicationContext(AppConfig.class);
      acac.close();
  }
}
  • AnnotationConfigApplicationContext

先來看一下AnnotationConfigApplicationContext類的UML圖,留個印象。程序員

AnnotationConfigApplicationContext

點開AnnotationConfigApplicationContext(AppConfig.class);方法查看源碼:spring

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {

    // 調用默認無參構造器,裏面有一大堆初始化邏輯
    // 開天闢地初始化兩個類
    // AnnotatedBeanDefinitionReader reader;
    // ClassPathBeanDefinitionScanner scanner;
    this();

    // 把傳入的Class進行註冊,Class既能夠有@Configuration註解,也能夠沒有@Configuration註解
    //
    // 有@Configuration
    // map.put("org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass","full")
    // 沒有有@Configuration
    // map.put("org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass","lite")
    //
    // 怎麼註冊? 委託給了 org.springframework.context.annotation.AnnotatedBeanDefinitionReader.register 方法進行註冊
    // 傳入Class 生成  BeanDefinition , 而後經過 註冊到 BeanDefinitionRegistry
    register(annotatedClasses);

    // 刷新容器上下文
    refresh();
}

該構造器容許咱們傳入一個或者多個class對象。class對象能夠是被@Configuration標註的,也能夠是一個普通的Java 類。app

有參構造器調用了無參構造器,點開源碼:ide

public AnnotationConfigApplicationContext() {
    // 隱式調用父類構造器,初始化beanFactory,具體實現類爲DefaultListableBeanFactory
    // super();

    // 建立 AnnotatedBeanDefinitionReader,
    // 建立時會向傳入的 BeanDefinitionRegistry 中 註冊 註解配置相關的 processors 的 BeanDefinition
    this.reader = new AnnotatedBeanDefinitionReader(this);

    // 經過後面的源碼探究也能夠發現,spring並非使用這個scanner來掃描包獲取Bean的
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

初始化子類時會先初始化父類,會默認調用父類無參構造器。AnnotationConfigApplicationContext繼承了GenericApplicationContext,在GenericApplicationContext的無參構造器中,建立了BeanFactory的具體實現類DefaultListableBeanFactory。spring中的BeanFactory就是在這裏被實例化的,而且使用DefaultListableBeanFactory作的BeanFactory的默認實現。函數

public GenericApplicationContext() {
    this.beanFactory = new DefaultListableBeanFactory();
}
  • DefaultListableBeanFactory

DefaultListableBeanFactory

AnnotationConfigApplicationContext的構造器中還建立了兩個對象:AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner。post

  • ClassPathBeanDefinitionScanner scanner

先說scanner的做用,經過查看源碼能夠發現,這個scanner只有在手動調用AnnotationConfigApplicationContext的一些方法的時候纔會被使用(經過後面的源碼探究也能夠發現,spring並非使用這個scanner來掃描包獲取Bean的)ui

二、AnnotatedBeanDefinitionReader

建立AnnotatedBeanDefinitionReader對象。spring在建立reader的時候把this當作了參數傳給了構造器。也就是說,reader對象裏面包含了一個this對象,也就是AnnotationConfigApplicationContext對象。AnnotationConfigApplicationContext 實現了BeanDefinitionRegistry接口。點開this.reader = new AnnotatedBeanDefinitionReader(this);源碼:this

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
    this(registry, getOrCreateEnvironment(registry));
}

從傳入的BeanDefinitionRegistry對象,也就是AnnotationConfigApplicationContext對象中獲取Environment(共用同一個Environment),而後又接着調用另外一個構造器。點開源碼:lua

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    Assert.notNull(environment, "Environment must not be null");
    this.registry = registry;
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);

    //在 BeanDefinitionRegistry 中註冊 註解配置相關的 processors
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

在這個構造器中,執行了一個很是重要的方法AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); 顧名思義,spring經過這個方法註冊瞭解析註解配置相關的處理器。點開源碼:

第一步:設置屬性

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, @Nullable Object source) {

    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    if (beanFactory != null) {
        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {

            // AnnotationAwareOrderComparator是OrderComparator的子類,用來支持Spring的Ordered類、@Order註解和@Priority註解。
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
        }
        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {

            // 設置依賴注入的候選處理器
            // 能夠看到只要不是ContextAnnotationAutowireCandidateResolver類型  直接升級爲最強類型
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }
    // 代碼省略。。。
}

註冊的是一些spring內置的PostProcessor的BeanDefinition

2.一、 ConfigurationClassPostProcessor

ConfigurationClassPostProcessor是一個BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor處理器,BeanDefinitionRegistryPostProcessor的處理方法能處理@Configuration等註解。ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry()方法內部處理@Configuration,@Import,@ImportResource和類內部的@Bean。

ConfigurationClassPostProcessor類繼承了BeanDefinitionRegistryPostProcessor。BeanDefinitionRegistryPostProcessor類繼承了BeanFactoryPostProcessor。經過BeanDefinitionRegistryPostProcessor能夠建立一個特別後置處理器來將BeanDefinition添加到BeanDefinitionRegistry中。它和BeanPostProcessor不一樣,BeanPostProcessor只是在Bean初始化的時候有個鉤子讓咱們加入一些自定義操做;而BeanDefinitionRegistryPostProcessor可讓咱們在BeanDefinition中添加一些自定義操做。在Mybatis與Spring的整合中,就利用到了BeanDefinitionRegistryPostProcessor來對Mapper的BeanDefinition進行了後置的自定義處理。

2.二、AutowiredAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor是用來處理@Autowired註解和@Value註解的

2.三、RequiredAnnotationBeanPostProcessor

RequiredAnnotationBeanPostProcessor這是用來處理@Required註解

2.四、CommonAnnotationBeanPostProcessor

提供對JSR-250規範註解的支持@javax.annotation.Resource、@javax.annotation.PostConstruct和@javax.annotation.PreDestroy等的支持。

2.五、EventListenerMethodProcessor

EventListenerMethodProcessor提供@PersistenceContext的支持。

EventListenerMethodProcessor提供@ EventListener 的支持。@ EventListener實在spring4.2以後出現的,能夠在一個Bean的方法上使用@EventListener註解來自動註冊一個ApplicationListener。

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, @Nullable Object source) {

    // 代碼省略。。。。

    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

    // 第一個問題 瞭解 RootBeanDefinition - > AbstractBeanDefinition
    // 第二個問題 瞭解 registerPostProcessor();
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {

        //org.springframework.context.annotation.internalConfigurationAnnotationProcessor - ConfigurationClassPostProcessor.class
        //這個類很是的重要,它是一個 BeanDefinitionRegistryPostProcessor

        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 代碼省略。。。。 邏輯差很少

    return beanDefs;
}

咱們發現:內部定義的class都是帶internal的

Set beanDefs

一、該方法從傳入的BeanDefinitionRegistry對象,也就是AnnotationConfigApplicationContext對象中獲取到DefaultListableBeanFactory對象。

二、爲獲取的DefaultListableBeanFactory對象設置屬性

三、往DefaultListableBeanFactory對象中註冊BeanDefinition,註冊的是一些spring內置的PostProcessor的BeanDefinition(關於BeanDefinition的介紹下期在講)。注意,此時只是註冊BeanDefinition,並無實例化bean。默認狀況下,執行完該方法後,spring容器中所註冊的BeanDefinition爲:

2.一、註冊內置Processor至容器

definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

ROLE_INFRASTRUCTURE = 2 就是我這Bean是Spring本身的,和你用戶沒有一毛錢關係

private static BeanDefinitionHolder registerPostProcessor(
        BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {

    definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    registry.registerBeanDefinition(beanName, definition);
    return new BeanDefinitionHolder(definition, beanName);
}

所謂的註冊BeanDefinition,簡單理解就是將BeanDefinition放到DefaultListableBeanFactory.registerBeanDefinition對象的beanDefinitionMap中

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        throws BeanDefinitionStoreException {

    Assert.hasText(beanName, "Bean name must not be empty");
    Assert.notNull(beanDefinition, "BeanDefinition must not be null");

    if (beanDefinition instanceof AbstractBeanDefinition) {
        try {
            ((AbstractBeanDefinition) beanDefinition).validate();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                    "Validation of bean definition failed", ex);
        }
    }

    BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);

    //第一次進來existingDefinition確定爲null
    if (existingDefinition != null) {
        // 代碼省略。。。
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    else {
        if (hasBeanCreationStarted()) {
            // Cannot modify startup-time collection elements anymore (for stable iteration)
            synchronized (this.beanDefinitionMap) {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                this.beanDefinitionNames = updatedDefinitions;
                removeManualSingletonName(beanName);
            }
        }
        else {
            // Still in startup registration phase
            this.beanDefinitionMap.put(beanName, beanDefinition);
            this.beanDefinitionNames.add(beanName);
            removeManualSingletonName(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }

    if (existingDefinition != null || containsSingleton(beanName)) {
        resetBeanDefinition(beanName);
    }
}

到此爲止:DefaultListableBeanFactory.beanDefinitionMap 只有默認的spring beanDefinition

====下面是你們熟悉的註冊默認6大後置處理器:====

  • 1.ConfigurationClassPostProcessor
  • 2.AutowiredAnnotationBeanPostProcessor
  • 3.CommonAnnotationBeanPostProcessor
  • 4.Jpa的PersistenceAnnotationProcessor(沒導包就不會註冊)
  • 5.EventListenerMethodProcessor
  • 6.DefaultEventListenerFactory

三、ClassPathBeanDefinitionScanner

public AnnotationConfigApplicationContext() {

  /**
    * 建立一個讀取註解的Bean定義讀取器
    * 什麼是bean定義?BeanDefinition
    *
    * 完成了spring內部BeanDefinition的註冊(主要是後置處理器)
    */
  this.reader = new AnnotatedBeanDefinitionReader(this);

  /**
    * 建立BeanDefinition掃描器
    * 能夠用來掃描包或者類,繼而轉換爲bd
    *
    * spring默認的掃描包不是這個scanner對象
    * 而是本身new的一個ClassPathBeanDefinitionScanner
    * spring在執行工程後置處理器ConfigurationClassPostProcessor時,去掃描包時會new一個ClassPathBeanDefinitionScanner
    *
    * 這裏的scanner僅僅是爲了程序員能夠手動調用AnnotationConfigApplicationContext對象的scan方法
    *
    */
  this.scanner = new ClassPathBeanDefinitionScanner(this);
}

下一步

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
			Environment environment, @Nullable ResourceLoader resourceLoader) {

	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
	this.registry = registry;

	// 這個確定成功
	if (useDefaultFilters) {

		/**
		 * 註冊spring掃描類過濾器
		 * 加了特定註解的類會被掃描到
		 * 帶有@Component、@Repository、@Service、@Controller、@ManagedBean、@Named
		 */
		registerDefaultFilters();
	}
	setEnvironment(environment);
	setResourceLoader(resourceLoader);
}

只關心最後一個構造函數的registerDefaultFilters();方法

/**
 * 註冊過濾器
 * 帶有@Component、@Repository、@Service、@Controller、@ManagedBean、@Named
 * 註解的類會被spring掃描到
 * 
 * Register the default filter for {@link Component @Component}.
 * <p>This will implicitly register all annotations that have the
 * {@link Component @Component} meta-annotation including the
 * {@link Repository @Repository}, {@link Service @Service}, and
 * {@link Controller @Controller} stereotype annotations.
 * <p>Also supports Java EE 6's {@link javax.annotation.ManagedBean} and
 * JSR-330's {@link javax.inject.Named} annotations, if available.
 *
 */
@SuppressWarnings("unchecked")
protected void registerDefaultFilters() {
	this.includeFilters.add(new AnnotationTypeFilter(Component.class));
	ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
	try {
		this.includeFilters.add(new AnnotationTypeFilter(
				((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
		logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
	}
	catch (ClassNotFoundException ex) {
		// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
	}
	try {
		this.includeFilters.add(new AnnotationTypeFilter(
				((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
		logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
	}
	catch (ClassNotFoundException ex) {
		// JSR-330 API not available - simply skip.
	}
}

掃描過濾器includeFilters與excludeFilters

首先這裏的includeFilters你們熟悉嗎,還有個excludeFilters,先看一下屬性

private final List<TypeFilter> includeFilters = new LinkedList<>();

	private final List<TypeFilter> excludeFilters = new LinkedList<>();

這裏提早往includeFilters裏面添加須要掃描的特定註解

1.添加元註解@Component,須要注意的是@Repository、@Service、@Controller裏面都標註了@Component。很好理解,掃描的時候用includeFilters 去過濾時,會找到並處理這4個註解的類。

2.下面兩個註解@ManagedBean、@Named須要有對應的jar包,不然(也就是說把這個方法走完),includeFilters裏面只會有一個元素

includeFilters

四、總結

this.reader = new AnnotatedBeanDefinitionReader(this); 完成了spring內部BeanDefinition的註冊(主要是後置處理器)

一、beanDefinitionMap存放了全部的Defintion 以 key-value

二、List<String> beanDefinitionNames 存放了全部的beanDefintion名字

this.scanner = new ClassPathBeanDefinitionScanner(this);

一、這裏的scanner僅僅是爲了程序員能夠手動調用AnnotationConfigApplicationContext對象的scan方法

二、提供了includeFilters 和 excludeFilters 這裏是一個擴展點

到此開天闢地初始化兩句代碼就完成了他們的使命。

x、彩蛋

一、ContextAnnotationAutowireCandidateResolver 後面解釋?

二、RootBeanDefinition -> AbstractBeanDefinition->BeanDefinition 後面解釋?

三、各類Processor解釋?

四、如何擴展includeFilters 和 excludeFilters 這裏是一個擴展點?

相關文章
相關標籤/搜索