spring之初始化上下文環(huán)境

本文的目的

  • 基于源碼快速的了解一個(gè)對(duì)象是怎么產(chǎn)生的
  • 我們可以怎么對(duì)spring的生產(chǎn)過(guò)程進(jìn)行干預(yù)

對(duì)象的一個(gè)大致創(chuàng)建流程

bean轉(zhuǎn)成bd放入到bdMap中,然后根據(jù)bean的名稱從bdMap中拿bd進(jìn)行創(chuàng)建,創(chuàng)建的時(shí)候會(huì)經(jīng)過(guò)一系列的后置處理器,最中返回我們需要?jiǎng)?chuàng)建的bean
最后會(huì)總結(jié)出來(lái)一張圖來(lái)解釋

構(gòu)建測(cè)試用例

  • 代碼如下
@Test
    public void registerBean() {
       // 1  初始化上下文環(huán)境 AnnotationConfigApplicationContext 
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
       //2 添加配置類
        context.register(Config.class, NameConfig.class);
       //3 執(zhí)行工廠的刷新方法
        context.refresh();
       //4  調(diào)用getBean方法 獲取對(duì)象
        TestBean testBean = (TestBean) context.getBean("testBean");
        assertEquals("foo", testBean.name);
    }

    @Configuration
    static class Config {
        @Bean
        public TestBean testBean() {
            TestBean testBean = new TestBean();
            testBean.name = "foo";
            return testBean;
        }
    }

    @Configuration
    static class NameConfig {
        @Bean
        String name() {
            return "foo";
        }
    }

由于篇幅原因,本章只解釋第一步驟 初始化上下文環(huán)境 AnnotationConfigApplicationContext

初始化上下文環(huán)境都做了一下什么事?

當(dāng)執(zhí)行了 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();這行代碼, 會(huì)執(zhí)行初始化的構(gòu)造方法;
根據(jù)繼承關(guān)系 AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry 可以看出,會(huì)先執(zhí)行 GenericApplicationContext的構(gòu)造方法,然后再執(zhí)行AnnotationConfigApplicationContext 的構(gòu)造方法

執(zhí)行GenericApplicationContext的構(gòu)造方法

    /**
     * 創(chuàng)建一個(gè) beanFactory
     * Create a new GenericApplicationContext.
     * @see #registerBeanDefinition
     * @see #refresh
     */
    public GenericApplicationContext() {
        this.beanFactory = new DefaultListableBeanFactory();
    }

創(chuàng)建一個(gè) DefaultListableBeanFactory 對(duì)象

    /**
     * Create a new DefaultListableBeanFactory.
     */
    public DefaultListableBeanFactory() {
        super();
    }

super()方法中在父類的實(shí)現(xiàn)

    /**
     * Create a new AbstractAutowireCapableBeanFactory.
     */
    public AbstractAutowireCapableBeanFactory() {
        super();
        //添加忽略依賴的接口 BeanNameAware
        ignoreDependencyInterface(BeanNameAware.class);
       //添加忽略依賴的接口 BeanFactoryAware
        ignoreDependencyInterface(BeanFactoryAware.class);
        //添加忽略依賴的接口 BeanClassLoaderAware
        ignoreDependencyInterface(BeanClassLoaderAware.class);
    }

執(zhí)行完構(gòu)造方法后是創(chuàng)建了一個(gè)DefaultListableBeanFactory對(duì)象,對(duì)象包含很多屬性,簡(jiǎn)要列舉下下邊會(huì)用到的屬性。

    /** key是bean的名稱value是BeanDefinition*/
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
    /** bean名稱的集合 */
    private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
    /**bean的后置處理器*/
    private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();

執(zhí)行AnnotationConfigApplicationContext本身的構(gòu)造方法

    /**
     * 創(chuàng)建注解配置類型的額上下文 本身也是一個(gè)注冊(cè)中心
     * 會(huì)調(diào)用父類方法    創(chuàng)建 beanFactory
     * Create a new AnnotationConfigApplicationContext that needs to be populated
     * through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
     */
    public AnnotationConfigApplicationContext() {
        // 注解bean定義信息解析器
        // 添加工廠的后置處理器 和bean的后置處理器
        this.reader = new AnnotatedBeanDefinitionReader(this);
        //掃描指定包下的bean轉(zhuǎn)成bd
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

這個(gè)構(gòu)造方法很重要
首先是實(shí)例化一個(gè)AnnotatedBeanDefinitionReader對(duì)象,這個(gè)對(duì)象的作用就是解析被注解的bean,轉(zhuǎn)換成beanDefinition;還有就是向容器中添加beanFactory的后置處理器和bean的后置處理器。注意這個(gè)構(gòu)造方法是需要傳入一個(gè) registry ,通過(guò)最開(kāi)始的繼承結(jié)構(gòu)可以知道AnnotationConfigApplicationContext 也實(shí)現(xiàn)了BeanDefinitionRegistry接口

創(chuàng)建ClassPathBeanDefinitionScanner對(duì)象,這個(gè)對(duì)象如果是采用的注解方式并且沒(méi)有手動(dòng)調(diào)用context.scan("org.springframework.context.xxx");這個(gè)方法實(shí)際上是沒(méi)有用的,看名稱我們可以知道,這個(gè)對(duì)象主要是掃描ClassPath下的bean轉(zhuǎn)換成BeanDefinition。但是實(shí)際在后邊真正處理的時(shí)候會(huì)重新新建一個(gè),在這次存在的意思就是類似與上邊我們手動(dòng)調(diào)用scan方法

所以接下來(lái)我們著重講解AnnotatedBeanDefinitionReader對(duì)象
當(dāng)我們調(diào)用這個(gè)對(duì)象的構(gòu)造方法的時(shí)候最終會(huì)進(jìn)入org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)這個(gè)方法
代碼如下

/**
     * Register all relevant annotation post processors in the given registry.
     *
     * @param registry the registry to operate on
     * @param source   the configuration source element (already extracted)
     *                 that this registration was triggered from. May be {@code null}.
     * @return a Set of BeanDefinitionHolders, containing all bean definitions
     * that have actually been registered by this call
     */
    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, @Nullable Object source) {
        //獲取 beanFactory  此處是 DefaultListableBeanFactory 看前邊的繼承關(guān)系
        DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
        if (beanFactory != null) {
            if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                //添加 排序的bean
                beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
            }
            if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
                //用于確定特定的Bean定義是否符合特定的依賴項(xiàng)的候選者的策略接口。
                //ContextAnnotationAutowireCandidateResolver這個(gè)是最全的一個(gè)策略接口可以處理Lazy
                //此處處理的lazy不是懶加載,是懶處理
                beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
            }
        }
        // BeanDefinitionHolder 是對(duì)  bd 和bean 名稱的一個(gè)封裝
        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
        //name=org.springframework.context.annotation.internalConfigurationAnnotationProcessor
        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            //添加  BeanDefinitionRegistryPostProcessor 類型的實(shí)現(xiàn)類   ConfigurationClassPostProcessor 也是 beanFactoryPostProcessor的實(shí)現(xiàn)類
            // ConfigurationClassPostProcessor 這個(gè)類的作用很大 會(huì)把我們程序中需要加載的bean轉(zhuǎn)乘bd從而被實(shí)例化成bean
            //后邊會(huì)著重講解
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
        }
        //org.springframework.context.annotation.internalAutowiredAnnotationProcessor
        if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            //添加BeanPostProcessor類型的實(shí)現(xiàn)類 AutowiredAnnotationBeanPostProcessor  主要是解決屬性自動(dòng)裝配問(wèn)題
            RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
        if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            //添加BeanPostProcessor類型的實(shí)現(xiàn)類 CommonAnnotationBeanPostProcessor  主要是處理類中的  PreDestroy ,PostConstruct ,Resource 這些注解
            RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
        if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition();
            try {
                def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                        AnnotationConfigUtils.class.getClassLoader()));
            } catch (ClassNotFoundException ex) {
                throw new IllegalStateException(
                        "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
            }
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
        }

        if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
        }

        return beanDefs;
    }

這個(gè)方法的主要主要作用就是向給定的注冊(cè)中心中加入beanFactory的后置處理器ConfigurationClassPostProcessor(會(huì)在refresh中重點(diǎn)講解)和一些bean的后置處理器比如 CommonAnnotationBeanPostProcessor主要負(fù)責(zé)處理類中的 PreDestroy ,PostConstruct ,Resource 這些注解。

執(zhí)行第二步向注冊(cè)中心添加配置類

代碼 context.register(Config.class, NameConfig.class);
方法最終調(diào)用 org.springframework.context.annotation.AnnotatedBeanDefinitionReader#doRegisterBean

/**
     * Register a bean from the given bean class, deriving its metadata from
     * class-declared annotations.
     * @param beanClass the class of the bean
     * @param instanceSupplier a callback for creating an instance of the bean
     * (may be {@code null})
     * @param name an explicit name for the bean
     * @param qualifiers specific qualifier annotations to consider, if any,
     * in addition to qualifiers at the bean class level
     * @param definitionCustomizers one or more callbacks for customizing the
     * factory's {@link BeanDefinition}, e.g. setting a lazy-init or primary flag
     * @since 5.0
     */
    <T> void doRegisterBean(Class<T> beanClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
            @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
        //傳進(jìn)來(lái)的類包裝成 AnnotatedGenericBeanDefinition 
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
        //是否需要跳過(guò) 一般不會(huì) 
        if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            return;
        }
        //注冊(cè)回到函數(shù)獲取對(duì)象 一般沒(méi)有
        abd.setInstanceSupplier(instanceSupplier);
        //解析作用域  如果沒(méi)有指定 默認(rèn)為單例 指定的化 根據(jù)注解上的信息獲取值
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        //設(shè)置作用域
        abd.setScope(scopeMetadata.getScopeName());
        //獲得一個(gè)bean的名稱
        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
        //處理通用注解信息  Lazy Primary  DependsOn Role  Description 如果有這些屬性 則取出賦值
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
        //qualifiers 類型的注解不為null的處理
        if (qualifiers != null) {
            for (Class<? extends Annotation> qualifier : qualifiers) {
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                }
                else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                }
                else {
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }
        //自定義函數(shù) 處理bd 一般沒(méi)有
        for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
            customizer.customize(abd);
        }
        //組裝成 definitionHolder 
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
        //應(yīng)用 ScopedProxyMode  判斷需不需要生成代理  一般不會(huì)用  上邊默認(rèn)為 no 
        //@Scope(value = "prototype",proxyMode= ScopedProxyMode.TARGET_CLASS) 則每次調(diào)用時(shí)都會(huì)生成一個(gè)對(duì)象
        //@Scope(value = "prototype") 同一個(gè)session 多次調(diào)用 產(chǎn)生同一個(gè)對(duì)象 不同的session調(diào)用每次都產(chǎn)生新的對(duì)象
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        //放入到bdMap中
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }

到現(xiàn)在位置構(gòu)造環(huán)境的前兩步就講完了,下一篇文章主要講解org.springframework.context.support.AbstractApplicationContext#refresh方法

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容