初学spring boot(扫盲)---001

1.这2天学了一下spring boot,为了扫盲spring cloud,记录学习心得。
2. 第一天简单回答几个问题:

(1)spring boot是如何内嵌tomcat容器的。

解答:这个我没看代码也大概猜到了,因为以前看ClassPathXmlApplicationContext源码的时候,AbstractApplicationContext的refresh()方法是有很多预留的扩展方法的,不出所料,spring boot正式通过AnnotationConfigEmbeddedWebApplicationContext类实现onRefresh()的方式内嵌tomcat容器的


@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();
			}
		}
	}


AnnotationConfigEmbeddedWebApplicationContext类实现onRefresh(),默认取得是TomcatEmbeddedServletContainer,可以切换到jetty 。
	@Override
	protected void onRefresh() {
		super.onRefresh();
		try {
			createEmbeddedServletContainer();
		}
		catch (Throwable ex) {
			throw new ApplicationContextException("Unable to start embedded container",
					ex);
		}
	}

/**
	 * Create a new {@link TomcatEmbeddedServletContainer} instance.
	 * @param tomcat the underlying Tomcat server
	 * @param autoStart if the server should be started
	 */
	public TomcatEmbeddedServletContainer(Tomcat tomcat, boolean autoStart) {
		Assert.notNull(tomcat, "Tomcat Server must not be null");
		this.tomcat = tomcat;
		this.autoStart = autoStart;
		initialize();
	}

	private synchronized void initialize() throws EmbeddedServletContainerException {
		TomcatEmbeddedServletContainer.logger
				.info("Tomcat initialized with port(s): " + getPortsDescription(false));
		try {
			addInstanceIdToEngineName();

			// Remove service connectors to that protocol binding doesn't happen yet
			removeServiceConnectors();

			// Start the server to trigger initialization listeners
			this.tomcat.start();

			// We can re-throw failure exception directly in the main thread
			rethrowDeferredStartupExceptions();

			// Unlike Jetty, all Tomcat threads are daemon threads. We create a
			// blocking non-daemon to stop immediate shutdown
			startDaemonAwaitThread();
		}
		catch (Exception ex) {
			throw new EmbeddedServletContainerException("Unable to start embedded Tomcat",
					ex);
		}
	}


切换到jetty也很简单:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <!-- 排除默认的tomcat,引入jetty容器. -->
    <exclusions>
      <exclusion>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
      </exclusion>
    </exclusions>
 </dependency>
 <!-- jetty 容器. -->
 <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-jetty</artifactId>
 </dependency>



(2)spring boot是如何注册bean到容器里面的:

解答:一般情况下,DefaultListableBeanFactory或者ClassPathXmlApplicationContext注册bean到容器都是通过解析XML默认标签和自定义标签的方式注册bean到容器里面的,最终存到DefaultListableBeanFactory的Map<String, BeanDefinition> beanDefinitionMap =new ConcurrentHashMap<String, BeanDefinition>(256);对象中的,而springboot是通过
"org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext"注册bean到容器中的,具体源码如下:
核心代码: load(context, sources.toArray(new Object[sources.size()]));

private ConfigurableApplicationContext createAndRefreshContext(
			SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments) {
		ConfigurableApplicationContext context;
		// Create and configure the environment
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		listeners.environmentPrepared(environment);
		if (isWebEnvironment(environment) && !this.webEnvironment) {
			environment = convertToStandardEnvironment(environment);
		}

		if (this.bannerMode != Banner.Mode.OFF) {
			printBanner(environment);
		}

		// Create, load, refresh and run the ApplicationContext
                context = createApplicationContext();
		context.setEnvironment(environment);
		postProcessApplicationContext(context);
		applyInitializers(context);
		listeners.contextPrepared(context);
		if (this.logStartupInfo) {
			logStartupInfo(context.getParent() == null);
			logStartupProfileInfo(context);
		}

		// Add boot specific singleton beans
		context.getBeanFactory().registerSingleton("springApplicationArguments",
				applicationArguments);

		// Load the sources
		Set<Object> sources = getSources();
		Assert.notEmpty(sources, "Sources must not be empty");
            load(context, sources.toArray(new Object[sources.size()]));
		listeners.contextLoaded(context);

		// Refresh the context
		refresh(context);
		if (this.registerShutdownHook) {
			try {
				context.registerShutdownHook();
			}
			catch (AccessControlException ex) {
				// Not allowed in some environments.
			}
		}
		return context;
	}




猜你喜欢

转载自ahua186186.iteye.com/blog/2321885
今日推荐