Spring Boot相关分析

SpringApplication

SpringApplication.run(Application.class,args…..)

public static ConfigurableApplicationContext run(Object[] sources, String[] args) {

//1.new SpringApplication()

//2.springapplication对象的run方法

              return new SpringApplication(sources).run(args);

}

1. new SpringApplication(sources)

public SpringApplication(Object... sources) {

                   initialize(sources);

 

         }

重点是initialize方法,下面是initialize方法,主要是初始化listeners等,给后面的run方法使用

 

private void initialize(Object[] sources) {
    //一般是上图的Application.class,填充sources
        if (sources != null && sources.length > 0) {
            this.sources.addAll(Arrays.asList(sources));
        }
        //判断是不是web环境,goto分析deduceWebEnvironment方法
        this.webEnvironment = deduceWebEnvironment();
        //实例化classpath路径下的jar包里的META-INF/spring.factories配置里的key为ApplicationContextInitializer的value值表示的类,然后setInitializers设值给initializers属性数组
        setInitializers((Collection) getSpringFactoriesInstances(
                ApplicationContextInitializer.class));
        //跟上面同理,实例化classpath路径下的jar包里的META-INF/spring.factories配置里的key为ApplicationListener的value值表示的类,然后setListeners设值给listeners属性数组
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        //得到main方法所在的类.class
this.mainApplicationClass = deduceMainApplicationClass();
    }







1.    分析deduceWebEnvironment方法
private boolean deduceWebEnvironment() {
//{ "javax.servlet.Servlet",
            "org.springframework.web.context.ConfigurableWebApplicationContext" }
//看{}数组里面的类在所有类路径下能否加载
        for (String className : WEB_ENVIRONMENT_CLASSES) {
    // ClassUtils,先用当前线程classloader如果为空在用加载ClassUtils的classLoader如果为空,再用SystemClassLoader
            if (!ClassUtils.isPresent(className, null)) {
                return false;
            }
        }
        return true;
    }

2. springapplication对象的run方法

 

public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        FailureAnalyzers analyzers = null;
        configureHeadlessProperty();
//1.goto  分析getRunListeners
        SpringApplicationRunListeners listeners = getRunListeners(args);
        // 调用SpringApplicationRunListener的start
        listeners.starting();
        try {
        //封装run的参数,重点是SpringApplication.class
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                    args);
        //更具webenviroment判断创建StandardServletEnvironment or StandardEnvironment
            ConfigurableEnvironment environment = prepareEnvironment(listeners,
                    applicationArguments);
            Banner printedBanner = printBanner(environment);


            //更具webenviroment,反射实例化容器
//org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext(webenviroment为true)
// or
// org.springframework.context. annotation.AnnotationConfigApplicationContext
context = createApplicationContext();
            analyzers = new FailureAnalyzers(context);
//2. goto分析prepareContext
            prepareContext(context, environment, listeners, applicationArguments,
                    printedBanner);
//这里是调用context的refresh方法,真正处理context的地方,读取annotation的配置,比如application类上的注解就是这个时候解析处理的
            refreshContext(context);
//调用容器中ApplicationRunner和CommandLineRunner的run方法,参数就是SpringApplication.run(class,…..)里面的….args
            afterRefresh(context, applicationArguments);
            //调用SpringApplicationRunListeners的每个SpringApplicationRunListener对象的finish方法
            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);
        }
    }





1.    分析getRunListeners
private SpringApplicationRunListeners getRunListeners(String[] args) {
        Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
        return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
                SpringApplicationRunListener.class, types, this, args));
    }


private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
            Class<?>[] parameterTypes, Object... args) {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
//读取classpath路径下的jar包里的META-INF/spring.factories配置里的key为SpringApplicationRunListener的value值
        Set<String> names = new LinkedHashSet<String>(
                SpringFactoriesLoader.loadFactoryNames(type, classLoader));
//根据SpringApplication和String 参数type 反射得到Constructor,然后实例化
        List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
                classLoader, args, names);
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
    }

2.    分析prepareContext
下面是方法代码:
private void prepareContext(ConfigurableApplicationContext context,
            ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
            ApplicationArguments applicationArguments, Banner printedBanner) {
        //给容器设置environment,可以读取里面的配置属性
        context.setEnvironment(environment);
        //注册单例bean(beanNameGenerator)和设置容器的resourceLoader,一般不会被创建,一般都是子类覆盖
        postProcessApplicationContext(context);
//调用initialize方法中实例化的类ApplicationContextInitializer的initialize参数是context
        applyInitializers(context);
//调用SpringApplicationRunListeners的每个SpringApplicationRunListener对象的contextPrepared方法
        listeners.contextPrepared(context);
        if (this.logStartupInfo) {
            logStartupInfo(context.getParent() == null);
            logStartupProfileInfo(context);
        }
//给容器添加单例springApplicationArguments和springBootBanner
        context.getBeanFactory().registerSingleton("springApplicationArguments",
                applicationArguments);
        if (printedBanner != null) {
            context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
        }

        //sources就是上面图里面添加了各种注解的application类的class
        Set<Object> sources = getSources();
        Assert.notEmpty(sources, "Sources must not be empty");
        //goto分析2.1 load方法
        load(context, sources.toArray(new Object[sources.size()]));
//调用SpringApplicationRunListeners的每个SpringApplicationRunListener对象的contextLoaded方法

        listeners.contextLoaded(context);
    }

2.1    分析load方法
protected void load(ApplicationContext context, Object[] sources) {
        if (logger.isDebugEnabled()) {
            logger.debug(
                    "Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
        }
//创建BeanDefinitionLoader,分析createBeanDefinitionLoader
        BeanDefinitionLoader loader = createBeanDefinitionLoader(
                getBeanDefinitionRegistry(context), sources);
        if (this.beanNameGenerator != null) {
        //设置BeanNameGenerator
            loader.setBeanNameGenerator(this.beanNameGenerator);
        }
        if (this.resourceLoader != null) {
        //设置ResourceLoader
loader.setResourceLoader(this.resourceLoader);
        }
        if (this.environment != null) {
        //设置environment
            loader.setEnvironment(this.environment);
        }
        //调用load加载配置
        loader.load();
    }

下面是createBeanDefinitionLoader方法代码
protected BeanDefinitionLoader createBeanDefinitionLoader(
            BeanDefinitionRegistry registry, Object[] sources) {
        return new BeanDefinitionLoader(registry, sources);
    }

BeanDefinitionLoader的构造方法:

BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
        Assert.notNull(registry, "Registry must not be null");
        Assert.notEmpty(sources, "Sources must not be empty");
        this.sources = sources;
//创建AnnotatedBeanDefinitionReader,annotation相关的,spring源码里面核心也是BeanDefinitionReader
        this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
//创建XmlBeanDefinitionReader,xml相关的
        this.xmlReader = new XmlBeanDefinitionReader(registry);
        if (isGroovyPresent()) {
    //groovy相关的
            this.groovyReader = new GroovyBeanDefinitionReader(registry);
        }
  //类路径的扫描器
        this.scanner = new ClassPathBeanDefinitionScanner(registry);
  //不扫描sources
        this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
    }

BeanDefinitionLoader的load方法:
private int load(Object source) {
        Assert.notNull(source, "Source must not be null");
        if (source instanceof Class<?>) {
        //一般情况下,调用的是这个分支,先看这个其他的可以以后看,一般是上面我们写了很多注解的application.class,主要逻辑就是将这个source  register 进reader(一般情况下是annotation相关,下面是load的代码)
            return load((Class<?>) source);
        }
        if (source instanceof Resource) {
            return load((Resource) source);
        }
        if (source instanceof Package) {
            return load((Package) source);
        }
        if (source instanceof CharSequence) {
            return load((CharSequence) source);
        }
        throw new IllegalArgumentException("Invalid source type " + source.getClass());
    }
    
    Load class分支代码:
    private int load(Class<?> source) {
        if (isGroovyPresent()) {
            // Any GroovyLoaders added in beans{} DSL can contribute beans here
            if (GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
                GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source,
                        GroovyBeanDefinitionSource.class);
                load(loader);
            }
        }
        if (isComponent(source)) {
            this.annotatedReader.register(source);
            return 1;
        }
        return 0;
    }

 

上面分析了springboot了整run的整个流程,重点是refreshContext方法,prepareContext方法会将相关的bean的类组装成BeanDefinition注册进context,我们像下面这样使用SpringBoot

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Application作为source registerContext,当refreshContext的时候会解析上面的注解,@Configuration@ComponentScan知道是spring的注解,@EnableAutoConfigurationboot的注解,看下定义:

@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    Class<?>[] exclude() default {};
    String[] excludeName() default {};
}

可以看到@Import(EnableAutoConfigurationImportSelector.class) 注解,看EnableAutoConfigurationImportSelector的定义

public class EnableAutoConfigurationImportSelector extends AutoConfigurationImportSelector

 

public class AutoConfigurationImportSelector

                   implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,

                   BeanFactoryAware, EnvironmentAware, Ordered 

可以看到EnableAutoConfigurationImportSelector类实现了ImportSelector接口,这个也是springjava config的扩展点,实现ImportSelector接口的类主要看方法selectImports方法,

public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        try {
            AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
                    .loadMetadata(this.beanClassLoader);
            AnnotationAttributes attributes = getAttributes(annotationMetadata);
            //读取META-INF/spring.factories的key为EnableAutoConfiguration的值,goto分析getCandidateConfigurations方法
            List<String> configurations = getCandidateConfigurations(annotationMetadata,
                    attributes);
            configurations = removeDuplicates(configurations);
            configurations = sort(configurations, autoConfigurationMetadata);
            Set<String> exclusions = getExclusions(annotationMetadata, attributes);
            checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            configurations = filter(configurations, autoConfigurationMetadata);
            fireAutoConfigurationImportEvents(configurations, exclusions);
            return configurations.toArray(new String[configurations.size()]);
        }
        catch (IOException ex) {
            throw new IllegalStateException(ex);
        }
    }

分析getCandidateConfigurations方法:
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
            AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
                getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
        Assert.notEmpty(configurations,
                "No auto configuration classes found in META-INF/spring.factories. If you "
                        + "are using a custom packaging, make sure that file is correct.");
        return configurations;
    }

可以看下META-INF/spring.factories下的配置片段

 

可以选Aopconfiguration看下,@ EnableAspectJAutoProxyspring相关的aop注解,其它类似,争对各方面的springjava config

@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

    @Configuration
    @EnableAspectJAutoProxy(proxyTargetClass = false)
    @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = true)
    public static class JdkDynamicAutoProxyConfiguration {

    }

    @Configuration
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = false)
    public static class CglibAutoProxyConfiguration {

    }
}
posted @ 2018-01-28 12:14  tom是cat  阅读(145)  评论(0)    收藏  举报