spring之初始化上下文环境

本文的目的

  • 基于源码快速的了解一个对象是怎么产生的
  • 我们可以怎么对spring的生产过程进行干预

对象的一个大致创建流程

bean转成bd放入到bdMap中,然后根据bean的名称从bdMap中拿bd进行创建,创建的时候会经过一系列的后置处理器,最中返回我们需要创建的bean
最后会总结出来一张图来解释

构建测试用例

  • 代码如下
@Test
    public void registerBean() {
       // 1  初始化上下文环境 AnnotationConfigApplicationContext 
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
       //2 添加配置类
        context.register(Config.class, NameConfig.class);
       //3 执行工厂的刷新方法
        context.refresh();
       //4  调用getBean方法 获取对象
        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";
        }
    }

由于篇幅原因,本章只解释第一步骤 初始化上下文环境 AnnotationConfigApplicationContext

初始化上下文环境都做了一下什么事?

当执行了 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();这行代码, 会执行初始化的构造方法;
根据继承关系 AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry 可以看出,会先执行 GenericApplicationContext的构造方法,然后再执行AnnotationConfigApplicationContext 的构造方法

执行GenericApplicationContext的构造方法

    /**
     * 创建一个 beanFactory
     * Create a new GenericApplicationContext.
     * @see #registerBeanDefinition
     * @see #refresh
     */
    public GenericApplicationContext() {
        this.beanFactory = new DefaultListableBeanFactory();
    }

创建一个 DefaultListableBeanFactory 对象

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

super()方法中在父类的实现

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

执行完构造方法后是创建了一个DefaultListableBeanFactory对象,对象包含很多属性,简要列举下下边会用到的属性。

    /** 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<>();

执行AnnotationConfigApplicationContext本身的构造方法

    /**
     * 创建注解配置类型的额上下文 本身也是一个注册中心
     * 会调用父类方法    创建 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转成bd
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

这个构造方法很重要
首先是实例化一个AnnotatedBeanDefinitionReader对象,这个对象的作用就是解析被注解的bean,转换成beanDefinition;还有就是向容器中添加beanFactory的后置处理器和bean的后置处理器。注意这个构造方法是需要传入一个 registry ,通过最开始的继承结构可以知道AnnotationConfigApplicationContext 也实现了BeanDefinitionRegistry接口

创建ClassPathBeanDefinitionScanner对象,这个对象如果是采用的注解方式并且没有手动调用context.scan("org.springframework.context.xxx");这个方法实际上是没有用的,看名称我们可以知道,这个对象主要是扫描ClassPath下的bean转换成BeanDefinition。但是实际在后边真正处理的时候会重新新建一个,在这次存在的意思就是类似与上边我们手动调用scan方法

所以接下来我们着重讲解AnnotatedBeanDefinitionReader对象
当我们调用这个对象的构造方法的时候最终会进入org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)这个方法
代码如下

/**
     * 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 看前边的继承关系
        DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
        if (beanFactory != null) {
            if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
                //添加 排序的bean
                beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
            }
            if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
                //用于确定特定的Bean定义是否符合特定的依赖项的候选者的策略接口。
                //ContextAnnotationAutowireCandidateResolver这个是最全的一个策略接口可以处理Lazy
                //此处处理的lazy不是懒加载,是懒处理
                beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
            }
        }
        // BeanDefinitionHolder 是对  bd 和bean 名称的一个封装
        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
        //name=org.springframework.context.annotation.internalConfigurationAnnotationProcessor
        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            //添加  BeanDefinitionRegistryPostProcessor 类型的实现类   ConfigurationClassPostProcessor 也是 beanFactoryPostProcessor的实现类
            // ConfigurationClassPostProcessor 这个类的作用很大 会把我们程序中需要加载的bean转乘bd从而被实例化成bean
            //后边会着重讲解
            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类型的实现类 AutowiredAnnotationBeanPostProcessor  主要是解决属性自动装配问题
            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类型的实现类 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;
    }

这个方法的主要主要作用就是向给定的注册中心中加入beanFactory的后置处理器ConfigurationClassPostProcessor(会在refresh中重点讲解)和一些bean的后置处理器比如 CommonAnnotationBeanPostProcessor主要负责处理类中的 PreDestroy ,PostConstruct ,Resource 这些注解。

执行第二步向注册中心添加配置类

代码 context.register(Config.class, NameConfig.class);
方法最终调用 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) {
        //传进来的类包装成 AnnotatedGenericBeanDefinition 
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
        //是否需要跳过 一般不会 
        if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            return;
        }
        //注册回到函数获取对象 一般没有
        abd.setInstanceSupplier(instanceSupplier);
        //解析作用域  如果没有指定 默认为单例 指定的化 根据注解上的信息获取值
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        //设置作用域
        abd.setScope(scopeMetadata.getScopeName());
        //获得一个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));
                }
            }
        }
        //自定义函数 处理bd 一般没有
        for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
            customizer.customize(abd);
        }
        //组装成 definitionHolder 
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
        //应用 ScopedProxyMode  判断需不需要生成代理  一般不会用  上边默认为 no 
        //@Scope(value = "prototype",proxyMode= ScopedProxyMode.TARGET_CLASS) 则每次调用时都会生成一个对象
        //@Scope(value = "prototype") 同一个session 多次调用 产生同一个对象 不同的session调用每次都产生新的对象
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        //放入到bdMap中
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }

到现在位置构造环境的前两步就讲完了,下一篇文章主要讲解org.springframework.context.support.AbstractApplicationContext#refresh方法

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350