Spring IOC

Spring Boot加载

​ Spring的IOC即控制反转,核心即将类的创建交给Spring工厂.Spring会扫描@MapperScan()指定的地址,将其中所有交给Spring容器管理的类(@Component,@Service,@Controller,@@Configuration等...)以Bean的形式放到Spring工厂.当需要某个类的时候,直接通过@Resource或者@Autowired即可完成类实例的装配.如果没有指定@MapperScan(),默认扫描启动类下所有包及子包.

1.启动类
@MapperScan("com.trevis.sharding.mapper")
@SpringBootApplication
public 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 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工厂的实现类.

Spring IOC_第1张图片

在GenericApplicationContext找到了beanFactory;

private final DefaultListableBeanFactory beanFactory;

@Nullable
private 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 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 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.完成刷新.

@Override
public 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);

你可能感兴趣的:(Spring IOC)