Spring Boot加载

Spring的IOC即管制反转,外围行将类的创立交给Spring工厂.Spring会扫描@MapperScan()指定的地址,将其中所有交给Spring容器治理的类(@Component,@Service,@Controller,@@Configuration等...)以Bean的模式放到Spring工厂.当须要某个类的时候,间接通过@Resource或者@Autowired即可实现类实例的拆卸.如果没有指定@MapperScan(),默认扫描启动类下所有包及子包.

1.启动类
@MapperScan("com.trevis.sharding.mapper")@SpringBootApplicationpublic class ShardingApplication {    public static void main(String[] args) {        SpringApplication.run(ShardingApplication.class, args);    }}
2.进入SpringApplication.Java构造函数初始化SpringApplication对象后调用run()办法;
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {        this.resourceLoader = resourceLoader;        Assert.notNull(primarySources, "PrimarySources must not be null");        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));        this.webApplicationType = WebApplicationType.deduceFromClasspath();        setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));        this.mainApplicationClass = deduceMainApplicationClass();    }public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {        return new SpringApplication(primarySources).run(args);    }
3.这里的返回值是ConfigurableApplicationContext,即返回利用上下文.在这里实现Bean的拆卸
  • Stopwatch: Spring计时器
  • SpringApplicationRunListeners: 监听器
  • ApplicationArguments: main办法启动时携带的参数,args大多数时候都是空的
  • Banner: 启动banner图
  • context = createApplicationContext(): 创立利用上下文
  • prepareContext(): 将主类信息加载到Spring容器
  • refreshContext(): 将扫描到的须要Sping治理的类加载到IOC容器
public ConfigurableApplicationContext run(String... args) {   StopWatch stopWatch = new StopWatch();   stopWatch.start();   ConfigurableApplicationContext context = null;   Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();   configureHeadlessProperty();   SpringApplicationRunListeners listeners = getRunListeners(args);   listeners.starting();   try {      ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);      ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);      configureIgnoreBeanInfo(environment);      Banner printedBanner = printBanner(environment);      context = createApplicationContext();      exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,            new Class[] { ConfigurableApplicationContext.class }, context);      prepareContext(context, environment, listeners, applicationArguments, printedBanner);      refreshContext(context);      afterRefresh(context, applicationArguments);      stopWatch.stop();      if (this.logStartupInfo) {         new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);      }      listeners.started(context);      callRunners(context, applicationArguments);   }   catch (Throwable ex) {      handleRunFailure(context, ex, exceptionReporters, listeners);      throw new IllegalStateException(ex);   }   try {      listeners.running(context);   }   catch (Throwable ex) {      handleRunFailure(context, ex, exceptionReporters, null);      throw new IllegalStateException(ex);   }   return context;}

依据初始化构造函数时的webApplicationType创立上下文.这里应该是SERVLET容器.

protected ConfigurableApplicationContext createApplicationContext() {   Class<?> contextClass = this.applicationContextClass;   if (contextClass == null) {      try {         switch (this.webApplicationType) {         case SERVLET:            contextClass = Class.forName(DEFAULT_SERVLET_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);}

获取context,依据webApplicationType通过反射加载如下类.这里并没有对于Bean工厂的创立,咱们去他的父类寻找.如图(略含糊),GenericApplicationContext是Bean工厂的实现类.

在GenericApplicationContext找到了beanFactory;

private final DefaultListableBeanFactory beanFactory;@Nullableprivate ResourceLoader resourceLoader;private boolean customClassLoader = false;private final AtomicBoolean refreshed = new AtomicBoolean();/** * Create a new GenericApplicationContext. * @see #registerBeanDefinition * @see #refresh */public GenericApplicationContext() {   this.beanFactory = new DefaultListableBeanFactory();}
4.实现Bean的注册

从上下文拿到Bean工厂

ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();

spring容器默认笼罩雷同bean

if (beanFactory instanceof DefaultListableBeanFactory) {   ((DefaultListableBeanFactory) beanFactory)         .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}

提早加载,默认false

if (this.lazyInitialization) {   context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());}
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,      SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {   context.setEnvironment(environment);   postProcessApplicationContext(context);   applyInitializers(context);   listeners.contextPrepared(context);   if (this.logStartupInfo) {      logStartupInfo(context.getParent() == null);      logStartupProfileInfo(context);   }   // Add boot specific singleton beans   ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();   beanFactory.registerSingleton("springApplicationArguments", applicationArguments);   if (printedBanner != null) {      beanFactory.registerSingleton("springBootBanner", printedBanner);   }   if (beanFactory instanceof DefaultListableBeanFactory) {      ((DefaultListableBeanFactory) beanFactory)            .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);   }   if (this.lazyInitialization) {      context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());   }   // Load the sources   Set<Object> sources = getAllSources();   Assert.notEmpty(sources, "Sources must not be empty");   load(context, sources.toArray(new Object[0]));   listeners.contextLoaded(context);}
5.BeanDefinitionLoader
6.是否被@Component注解,如果是,注册bin.(@Controller @Service等都是@Component的子注解)
private int load(Class<?> source) {   if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {      // Any GroovyLoaders added in beans{} DSL can contribute beans here      GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);      load(loader);   }   if (isComponent(source)) {      this.annotatedReader.register(source);      return 1;   }   return 0;}
public void register(Class<?>... componentClasses) {   for (Class<?> componentClass : componentClasses) {      registerBean(componentClass);   }}
public void registerBean(Class<?> beanClass) {   doRegisterBean(beanClass, null, null, null, null);}
7.doRegisterBean注册bean

这里看到,Spring将bean放到了beanDefinitionMap这个map容器中,.到这里就差不多实现了bean注册.

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);this.beanDefinitionMap.put(beanName, beanDefinition);
8.refreshContext

刷新利用上下文,注册bean,实现Spring IOC容器初始化.

1.筹备刷新--->2.获取刷新bean工厂--->3.筹备bean工厂--->4.前解决bean工厂--->

5.调用bean工厂前处理器--->6.注册bean前处理器--->7.初始化音讯源--->8.初始化利用事件公布器--->

9.刷新--->10.注册监听器--->11.实现bean工厂初始化--->12.实现刷新.

@Overridepublic void refresh() throws BeansException, IllegalStateException {   synchronized (this.startupShutdownMonitor) {      // Prepare this context for refreshing.      prepareRefresh();      // Tell the subclass to refresh the internal bean factory.      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();      // Prepare the bean factory for use in this context.      prepareBeanFactory(beanFactory);      try {         // Allows post-processing of the bean factory in context subclasses.         postProcessBeanFactory(beanFactory);         // Invoke factory processors registered as beans in the context.         invokeBeanFactoryPostProcessors(beanFactory);         // Register bean processors that intercept bean creation.         registerBeanPostProcessors(beanFactory);         // Initialize message source for this context.         initMessageSource();         // Initialize event multicaster for this context.         initApplicationEventMulticaster();         // Initialize other special beans in specific context subclasses.         onRefresh();         // Check for listener beans and register them.         registerListeners();         // Instantiate all remaining (non-lazy-init) singletons.         finishBeanFactoryInitialization(beanFactory);         // Last step: publish corresponding event.         finishRefresh();      }      catch (BeansException ex) {         if (logger.isWarnEnabled()) {            logger.warn("Exception encountered during context initialization - " +                  "cancelling refresh attempt: " + ex);         }         // Destroy already created singletons to avoid dangling resources.         destroyBeans();         // Reset 'active' flag.         cancelRefresh(ex);         // Propagate exception to caller.         throw ex;      }      finally {         // Reset common introspection caches in Spring's core, since we         // might not ever need metadata for singleton beans anymore...         resetCommonCaches();      }   }}

初始化工厂

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {   // Tell the internal bean factory to use the context's class loader etc.   beanFactory.setBeanClassLoader(getClassLoader());   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));   // Configure the bean factory with context callbacks.   beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));   beanFactory.ignoreDependencyInterface(EnvironmentAware.class);   beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);   beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);   beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);   beanFactory.ignoreDependencyInterface(MessageSourceAware.class);   beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);   // BeanFactory interface not registered as resolvable type in a plain factory.   // MessageSource registered (and found for autowiring) as a bean.   beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);   beanFactory.registerResolvableDependency(ResourceLoader.class, this);   beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);   beanFactory.registerResolvableDependency(ApplicationContext.class, this);   // Register early post-processor for detecting inner beans as ApplicationListeners.   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));   // Detect a LoadTimeWeaver and prepare for weaving, if found.   if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));      // Set a temporary ClassLoader for type matching.      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));   }   // Register default environment beans.   if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {      beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());   }   if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {      beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());   }   if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {      beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());   }}

实现bean的注册

invokeBeanFactoryPostProcessors(beanFactory);