Spring源码(二)-Context的创建(上)

来源:互联网 发布:索尼电视推荐 知乎 编辑:程序博客网 时间:2024/06/01 07:31

我们前一章介绍了spring的整体架构以及模块划分,也已经将代码导入ide中,那么接下来就要开始让人心动的Spring源码之旅了。

1、默认的Spring启动器

@SpringBootApplication@ComponentScan(basePackages = {"com"})public class SpringSourceApplication {    public static void main(String[] args) {        ApplicationContext ctx = SpringApplication.run(SpringSourceApplication.class, args);    }}

该方法是Springboot的启动类

2、进入SpringApplication.java

public static ConfigurableApplicationContext run(Object source, String... args) {    return run(new Object[] { source }, args);}
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {    return new SpringApplication(sources).run(args);}


这里创建了一个SpringApplication方法,执行run方法,返回一个ConfigurableApplicationContext,这只是一个接口而已,根据名称来看,这是一个可配置的应用程序上下文。

3、进入run方法

SpringApplication(sources)这个类的初始化就先不看,这里面调用了initialize()方法,主要完成了当前的运行环境,以及设置了ApplicationListener相关的东西,这里我们先不做分析,直接进入run方法。

    public ConfigurableApplicationContext run(String... args) {        //记录程序运行时间        StopWatch stopWatch = new StopWatch();        stopWatch.start();        ConfigurableApplicationContext context = null;        FailureAnalyzers analyzers = null;        /**         * 设置headless模式         * 在我们的例子中该属性会被设置为true,因为我们开发的是服务器程序,         * 一般运行在没有显示器和键盘的环境。关于java中的headless模式         */        configureHeadlessProperty();        SpringApplicationRunListeners listeners = getRunListeners(args);        listeners.starting();        try {            ApplicationArguments applicationArguments = new DefaultApplicationArguments(                    args);            ConfigurableEnvironment environment = prepareEnvironment(listeners,                    applicationArguments);            configureIgnoreBeanInfo(environment);            bindToSpringApplication(environment);            Banner printedBanner = printBanner(environment);            /**             * 它创建出来的是ConfigurableApplicationContext类的实例对象             *AnnotationConfigEmbeddedWebApplicationContext             */            context = createApplicationContext();            analyzers = new FailureAnalyzers(context);            /**             *  该方法对context进行了预设置,设置了ResourceLoader和ClassLoader,             *  并向bean工厂中添加了一个beanNameGenerator             */            prepareContext(context, environment, listeners, applicationArguments,                    printedBanner);            /**             * prepareContext()已经做好了refresh上下文的基础准备工作             * spring对ApplicationContext进行了向下转型,             * 转型后的类型为:AbstractApplicationContex,并调用了它的refresh()方法             * 详见方法内部实现             */            refreshContext(context);            afterRefresh(context, applicationArguments);            listeners.finished(context, null);            stopWatch.stop();            if (this.logStartupInfo) {                new StartupInfoLogger(this.mainApplicationClass)                        .logStarted(getApplicationLog(), stopWatch);            }            return context;        }        catch (Throwable ex) {            handleRunFailure(context, listeners, analyzers, ex);            throw new IllegalStateException(ex);        }    }

try代码块中是我们最核心的功能,代码中也添加了一部分的注释。我们先看context的创建过程即进入到createApplicationContext()方法。

protected ConfigurableApplicationContext createApplicationContext() {    Class<?> contextClass = this.applicationContextClass;    if (contextClass == null) {        try {            switch (this.webApplicationType) {                case SERVLET:                    //此处采用反射获取WebApplicationContext                    contextClass = Class.forName(DEFAULT_WEB_CONTEXT_CLASS);                    break;                case REACTIVE:                    contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);                    break;                default:                    contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);            }        }        catch (ClassNotFoundException ex) {            throw new IllegalStateException(                    "Unable create a default ApplicationContext, "                            + "please specify an ApplicationContextClass",                    ex);        }    }    return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);}

DEFAULT_WEB_CONTEXT_CLASS —>AnnotationConfigEmbeddedWebApplicationContext
接下来执行AnnotationConfigEmbeddedWebApplicationContext的构造方法

public AnnotationConfigEmbeddedWebApplicationContext() {          this.reader = new AnnotatedBeanDefinitionReader(this);          this.scanner = new ClassPathBeanDefinitionScanner(this);  }  

上面实例化了AnnotatedBeanDefinitionReader以及ClassPathBeanDefinitionScanner
实例化AnnotatedBeanDefinitionReader

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

接下来是调用

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);          AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);      }  

实例化 ConditionEvaluator,将其属性ConditionContextImpl赋值

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);  

具体实现如下:

    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(            BeanDefinitionRegistry registry, @Nullable Object source) {        //获取beanfactory信息,Spring IOC的核心        DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry)        if (beanFactory != null) {            if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {                beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);            }            if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {                beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());            }        }        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(4);        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);            def.setSource(source);            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));        }        if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {            RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);            def.setSource(source);            beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));        }        if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {            RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);            def.setSource(source);            beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));        }        // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.        if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {            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;    }

上面代码比较长,我们来分开解析
- 1、DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
由wrap就可以看出此处使用的是装饰器模式,registry包裹成一个指定的beanFactory

private static DefaultListableBeanFactory unwrapDefaultListableBeanFactory(BeanDefinitionRegistry registry) {    if (registry instanceof DefaultListableBeanFactory) {        return (DefaultListableBeanFactory) registry;    }    else if (registry instanceof GenericApplicationContext) {        //此处 GenericApplicationContext构造函数初始化beanFactory为DefaultListableBeanFactory        return ((GenericApplicationContext) registry).getDefaultListableBeanFactory();    }    else {        return null;    }}

代码执行到registry instanceof GenericApplicationContext(通过类继承结构可得到),随后调用GenericApplicationContext#getDefaultListableBeanFactory()方法,GenericApplicationContext在构造方法中实例化了属性beanFactory的值为DefaultListableBeanFactory:

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

其构造优先于AnnotationConfigEmbeddedWebApplicationContext构造方法执行。
以上获得了BeanFactory信息

代码的构建请参考 github
该地址有相应代码的注释

Spring源码分析

  • 1、Spring源码(一)-Spring整体架构和环境搭建
  • 2、Spring源码(二)-Context的创建(上)
  • 3、Spring源码(三)-Context的创建(下)
原创粉丝点击