真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Spring5.x中容器啟動(dòng)源碼怎么寫

今天就跟大家聊聊有關(guān) Spring5.x 中容器啟動(dòng)源碼怎么寫,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

創(chuàng)新互聯(lián)建站主營(yíng)常山網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,重慶APP軟件開發(fā),常山h5成都小程序開發(fā)搭建,常山網(wǎng)站營(yíng)銷推廣歡迎常山等地區(qū)企業(yè)咨詢

Spring 已經(jīng)是十分成熟的一個(gè)框架,此篇為開天辟地的Spring源碼分析首發(fā)。讀源碼本來就是一件十分枯燥,具有一定難度,技巧性的有重要意義的事。萬事開頭難,我會(huì)利用空余時(shí)間持續(xù)的跟進(jìn)文章的連載。對(duì)于喜愛源碼的小伙伴,能夠提供一定的幫助。

最簡(jiǎn)單的啟動(dòng)spring的代碼如下:

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圖,留個(gè)印象。

Spring5.x 中容器啟動(dòng)源碼怎么寫

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

public AnnotationConfigApplicationContext(Class... annotatedClasses) {

    // 調(diào)用默認(rèn)無參構(gòu)造器,里面有一大堆初始化邏輯
    // 開天辟地初始化兩個(gè)類
    // AnnotatedBeanDefinitionReader reader;
    // ClassPathBeanDefinitionScanner scanner;
    this();

    // 把傳入的Class進(jìn)行注冊(cè),Class既可以有@Configuration注解,也可以沒有@Configuration注解
    //
    // 有@Configuration
    // map.put("org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass","full")
    // 沒有有@Configuration
    // map.put("org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass","lite")
    //
    // 怎么注冊(cè)? 委托給了 org.springframework.context.annotation.AnnotatedBeanDefinitionReader.register 方法進(jìn)行注冊(cè)
    // 傳入Class 生成  BeanDefinition , 然后通過 注冊(cè)到 BeanDefinitionRegistry
    register(annotatedClasses);

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

該構(gòu)造器允許我們傳入一個(gè)或者多個(gè)class對(duì)象。class對(duì)象可以是被@Configuration標(biāo)注的,也可以是一個(gè)普通的Java 類。

有參構(gòu)造器調(diào)用了無參構(gòu)造器,點(diǎn)開源碼:

public AnnotationConfigApplicationContext() {
    // 隱式調(diào)用父類構(gòu)造器,初始化beanFactory,具體實(shí)現(xiàn)類為DefaultListableBeanFactory
    // super();

    // 創(chuàng)建 AnnotatedBeanDefinitionReader,
    // 創(chuàng)建時(shí)會(huì)向傳入的 BeanDefinitionRegistry 中 注冊(cè) 注解配置相關(guān)的 processors 的 BeanDefinition
    this.reader = new AnnotatedBeanDefinitionReader(this);

    // 通過后面的源碼探究也可以發(fā)現(xiàn),spring并不是使用這個(gè)scanner來掃描包獲取Bean的
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

初始化子類時(shí)會(huì)先初始化父類,會(huì)默認(rèn)調(diào)用父類無參構(gòu)造器。AnnotationConfigApplicationContext繼承了GenericApplicationContext,在GenericApplicationContext的無參構(gòu)造器中,創(chuàng)建了BeanFactory的具體實(shí)現(xiàn)類DefaultListableBeanFactory。spring中的BeanFactory就是在這里被實(shí)例化的,并且使用DefaultListableBeanFactory做的BeanFactory的默認(rèn)實(shí)現(xiàn)。

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

Spring5.x 中容器啟動(dòng)源碼怎么寫

AnnotationConfigApplicationContext的構(gòu)造器中還創(chuàng)建了兩個(gè)對(duì)象:AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner。

  • ClassPathBeanDefinitionScanner scanner

先說scanner的作用,通過查看源碼可以發(fā)現(xiàn),這個(gè)scanner只有在手動(dòng)調(diào)用AnnotationConfigApplicationContext的一些方法的時(shí)候才會(huì)被使用(通過后面的源碼探究也可以發(fā)現(xiàn),spring并不是使用這個(gè)scanner來掃描包獲取Bean的)

Spring5.x 中容器啟動(dòng)源碼怎么寫

2、AnnotatedBeanDefinitionReader

創(chuàng)建AnnotatedBeanDefinitionReader對(duì)象。spring在創(chuàng)建reader的時(shí)候把this當(dāng)做了參數(shù)傳給了構(gòu)造器。也就是說,reader對(duì)象里面包含了一個(gè)this對(duì)象,也就是AnnotationConfigApplicationContext對(duì)象。AnnotationConfigApplicationContext 實(shí)現(xiàn)了BeanDefinitionRegistry接口。點(diǎn)開this.reader = new AnnotatedBeanDefinitionReader(this);源碼:

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

從傳入的BeanDefinitionRegistry對(duì)象,也就是AnnotationConfigApplicationContext對(duì)象中獲取Environment(共用同一個(gè)Environment),然后又接著調(diào)用另一個(gè)構(gòu)造器。點(diǎn)開源碼:

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 中注冊(cè) 注解配置相關(guān)的 processors
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

在這個(gè)構(gòu)造器中,執(zhí)行了一個(gè)非常重要的方法AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); 顧名思義,spring通過這個(gè)方法注冊(cè)了解析注解配置相關(guān)的處理器。點(diǎn)開源碼:

第一步:設(shè)置屬性

public static Set 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)) {

            // 設(shè)置依賴注入的候選處理器
            // 可以看到只要不是ContextAnnotationAutowireCandidateResolver類型  直接升級(jí)為最強(qiáng)類型
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }
    // 代碼省略。。。
}

注冊(cè)的是一些spring內(nèi)置的PostProcessor的BeanDefinition

2.1、 ConfigurationClassPostProcessor

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

ConfigurationClassPostProcessor類繼承了BeanDefinitionRegistryPostProcessor。BeanDefinitionRegistryPostProcessor類繼承了BeanFactoryPostProcessor。通過BeanDefinitionRegistryPostProcessor可以創(chuàng)建一個(gè)特別后置處理器來將BeanDefinition添加到BeanDefinitionRegistry中。它和BeanPostProcessor不同,BeanPostProcessor只是在Bean初始化的時(shí)候有個(gè)鉤子讓我們加入一些自定義操作;而BeanDefinitionRegistryPostProcessor可以讓我們?cè)贐eanDefinition中添加一些自定義操作。在Mybatis與Spring的整合中,就利用到了BeanDefinitionRegistryPostProcessor來對(duì)Mapper的BeanDefinition進(jìn)行了后置的自定義處理。

2.2、AutowiredAnnotationBeanPostProcessor

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

2.3、RequiredAnnotationBeanPostProcessor

RequiredAnnotationBeanPostProcessor這是用來處理@Required注解

2.4、CommonAnnotationBeanPostProcessor

提供對(duì)JSR-250規(guī)范注解的支持@javax.annotation.Resource、@javax.annotation.PostConstruct和@javax.annotation.PreDestroy等的支持。

2.5、EventListenerMethodProcessor

EventListenerMethodProcessor提供@PersistenceContext的支持。

EventListenerMethodProcessor提供@ EventListener 的支持。@ EventListener實(shí)在spring4.2之后出現(xiàn)的,可以在一個(gè)Bean的方法上使用@EventListener注解來自動(dòng)注冊(cè)一個(gè)ApplicationListener。

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

    // 代碼省略。。。。

    Set beanDefs = new LinkedHashSet<>(8);

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

        //org.springframework.context.annotation.internalConfigurationAnnotationProcessor - ConfigurationClassPostProcessor.class
        //這個(gè)類非常的重要,它是一個(gè) BeanDefinitionRegistryPostProcessor

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

    // 代碼省略。。。。 邏輯差不多

    return beanDefs;
}

我們發(fā)現(xiàn):內(nèi)部定義的class都是帶internal的

Spring5.x 中容器啟動(dòng)源碼怎么寫 beanDefs">

1、該方法從傳入的BeanDefinitionRegistry對(duì)象,也就是AnnotationConfigApplicationContext對(duì)象中獲取到DefaultListableBeanFactory對(duì)象。

2、為獲取的DefaultListableBeanFactory對(duì)象設(shè)置屬性

3、往DefaultListableBeanFactory對(duì)象中注冊(cè)BeanDefinition,注冊(cè)的是一些spring內(nèi)置的PostProcessor的BeanDefinition(關(guān)于BeanDefinition的介紹下期在講)。注意,此時(shí)只是注冊(cè)BeanDefinition,并沒有實(shí)例化bean。默認(rèn)情況下,執(zhí)行完該方法后,spring容器中所注冊(cè)的BeanDefinition為:

2.1、注冊(cè)內(nèi)置Processor至容器

definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

ROLE_INFRASTRUCTURE = 2 就是我這Bean是Spring自己的,和你用戶沒有一毛錢關(guān)系

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

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

所謂的注冊(cè)BeanDefinition,簡(jiǎn)單理解就是將BeanDefinition放到DefaultListableBeanFactory.registerBeanDefinition對(duì)象的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);

    //第一次進(jìn)來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 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 只有默認(rèn)的spring beanDefinition

====下面是大家熟悉的注冊(cè)默認(rèn)6大后置處理器:====

  • 1.ConfigurationClassPostProcessor

  • 2.AutowiredAnnotationBeanPostProcessor

  • 3.CommonAnnotationBeanPostProcessor

  • 4.Jpa的PersistenceAnnotationProcessor(沒導(dǎo)包就不會(huì)注冊(cè))

  • 5.EventListenerMethodProcessor

  • 6.DefaultEventListenerFactory

3、ClassPathBeanDefinitionScanner

public AnnotationConfigApplicationContext() {

  /**
    * 創(chuàng)建一個(gè)讀取注解的Bean定義讀取器
    * 什么是bean定義?BeanDefinition
    *
    * 完成了spring內(nèi)部BeanDefinition的注冊(cè)(主要是后置處理器)
    */
  this.reader = new AnnotatedBeanDefinitionReader(this);

  /**
    * 創(chuàng)建BeanDefinition掃描器
    * 可以用來掃描包或者類,繼而轉(zhuǎn)換為bd
    *
    * spring默認(rèn)的掃描包不是這個(gè)scanner對(duì)象
    * 而是自己new的一個(gè)ClassPathBeanDefinitionScanner
    * spring在執(zhí)行工程后置處理器ConfigurationClassPostProcessor時(shí),去掃描包時(shí)會(huì)new一個(gè)ClassPathBeanDefinitionScanner
    *
    * 這里的scanner僅僅是為了程序員可以手動(dòng)調(diào)用AnnotationConfigApplicationContext對(duì)象的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;

	// 這個(gè)肯定成功
	if (useDefaultFilters) {

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

只關(guān)心最后一個(gè)構(gòu)造函數(shù)的registerDefaultFilters();方法

/**
 * 注冊(cè)過濾器
 * 帶有@Component、@Repository、@Service、@Controller、@ManagedBean、@Named
 * 注解的類會(huì)被spring掃描到
 * 
 * Register the default filter for {@link Component @Component}.
 * 

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.  * 

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) 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) 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大家熟悉嗎,還有個(gè)excludeFilters,先看一下屬性

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

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

這里提前往includeFilters里面添加需要掃描的特定注解

1.添加元注解@Component,需要注意的是@Repository、@Service、@Controller里面都標(biāo)注了@Component。很好理解,掃描的時(shí)候用includeFilters 去過濾時(shí),會(huì)找到并處理這4個(gè)注解的類。

2.下面兩個(gè)注解@ManagedBean、@Named需要有對(duì)應(yīng)的jar包,否則(也就是說把這個(gè)方法走完),includeFilters里面只會(huì)有一個(gè)元素

Spring5.x 中容器啟動(dòng)源碼怎么寫

this.reader = new AnnotatedBeanDefinitionReader(this); 完成了spring內(nèi)部BeanDefinition的注冊(cè)(主要是后置處理器)

1、beanDefinitionMap存放了所有的Defintion 以 key-value

2、List beanDefinitionNames 存放了所有的beanDefintion名字

this.scanner = new ClassPathBeanDefinitionScanner(this);

1、這里的scanner僅僅是為了程序員可以手動(dòng)調(diào)用AnnotationConfigApplicationContext對(duì)象的scan方法

2、提供了includeFilters 和 excludeFilters 這里是一個(gè)擴(kuò)展點(diǎn)

看完上述內(nèi)容,你們對(duì) Spring5.x 中容器啟動(dòng)源碼怎么寫有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。


分享標(biāo)題:Spring5.x中容器啟動(dòng)源碼怎么寫
鏈接URL:http://weahome.cn/article/piopjd.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部