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 register进Context,当refreshContext的时候会解析上面的注解,@Configuration和@ComponentScan知道是spring的注解,@EnableAutoConfiguration是boot的注解,看下定义:
@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接口,这个也是spring的java 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下的配置片段

可以选Aop的configuration看下,@ EnableAspectJAutoProxy是spring相关的aop注解,其它类似,争对各方面的spring的java 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 { } }
浙公网安备 33010602011771号