网站建设论文范文如何将百度云做成网站文件服务器

当前位置: 首页 > news >正文

网站建设论文范文,如何将百度云做成网站文件服务器,5g国产天天5g天天,做苗木网站哪个公司好SPI 在分析源码前#xff0c;我们先来了解下 spring 的 SPI 机制。我们知道#xff0c;jdk 为了方便应用程序进行扩展#xff0c;提供了默认的 SPI 实现#xff08;ServiceLoader#xff09;#xff0c;dubbo 也有自己的 SPI。spring 也是如此#xff0c;他为我们提供了…SPI 在分析源码前我们先来了解下 spring 的 SPI 机制。我们知道jdk 为了方便应用程序进行扩展提供了默认的 SPI 实现ServiceLoaderdubbo 也有自己的 SPI。spring 也是如此他为我们提供了 SpringFactoriesLoader允许开发人员通过 META-INF/spring.factories 文件进行扩展下面举一个例子方便理解 假如我想要往 spring 容器中添加一个 ApplicationContextInitializer 做一些初始化工作我们可以借助 spring 提供的这个 SPI 功能完成这个需求。 首先在项目中创建 META-INF/spring.factories 文件文件内容如下所示 org.springframework.context.ApplicationContextInitializer\ 我们再写个 test case便可以通过 SPI 的方式获取我们定义的 ApplicationContextInitializer。看似很简单的一个功能但是 spring boot 正是利用这个强大的扩展点在 spring framework 的基础上为我们集成了常用的开源框架 Test public void testSpringSpi() {ListApplicationListener listeners SpringFactoriesLoader.loadFactories( ApplicationListener.class, ClassUtils.getDefaultClassLoader() );System.out.println( listeners ); 我们再来看看这个 SpringFactoriesLoader关键代码如下所示它通过读取 META-INF/spring.factories 文件并且查找方法参数指定的 class然后创建对应的实例对象并且返回。此外还支持排序可以使用以下几种方式进行排序 org.springframework.core.Ordered实现该接口org.springframework.core.annotation.Order注解javax.annotation.Priority注解 public static T ListT loadFactories(ClassT factoryClass, ClassLoader classLoader) {ListString factoryNames loadFactoryNames(factoryClass, classLoaderToUse);ListT result new ArrayListT(factoryNames.size());for (String factoryName : factoryNames) {result.add(instantiateFactory(factoryName, factoryClass, classLoaderToUse));}AnnotationAwareOrderComparator.sort(result);return result; 接下来我们来分析下 spring boot 是如何利用 SPI 机制集成 tomcat Spring Boot for Tomcat 在分析 tomcat 集成的源码之前我们先来了解下 EmbeddedServletContainer EmbeddedServletContainer spring 用 EmbeddedServletContainer 封装了内嵌的 servlet 容器提供了start、stop 等接口用于控制容器的生命周期并且 spring 内置了 tomcat、jetty、undertow 容器的实现类图所下所示 我们再来看看 spring boot 中最常用的 SpringBootApplication 注解原来是多个注解的综合体而这个 EnableAutoConfiguration 便是 spring boot 用做自动化配置的注解 SpringBootConfiguration EnableAutoConfiguration ComponentScan(excludeFilters {Filter(type FilterType.CUSTOM, classes TypeExcludeFilter.class),Filter(type FilterType.CUSTOM, classes AutoConfigurationExcludeFilter.class) }) public interface SpringBootApplication {// code…… 我们在 spring-boot-autoconfigure 模块可以看到大量的 SPI 配置部分如下所示

Auto Configure

org.springframework.boot.autoconfigure.EnableAutoConfiguration
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\ 原来 EnableAutoConfiguration 注解引入了 EmbeddedServletContainerAutoConfiguration而这个便是内嵌 servlet 容器的配置类tomcat、jetty、undertow 都在这个类上面通过 ConditionalOnClass 注解加载不同的 servlet 容器。但是这个类仅仅是注册了 TomcatEmbeddedServletContainerFactory 不足以帮助我们解除所有的困惑。不要急我们先来看看 TomcatEmbeddedServletContainerFactory 的类图。 由上面的类图可知它实现了以下接口 EmbeddedServletContainerFactory它是一个工厂模式用于创建 EmbeddedServletContainer即用于创建一个内嵌的 Servlet 容器这个接口里面只有一个 getEmbeddedServletContainer 方法ConfigurableEmbeddedServletContainer用于配置 EmbeddedServletContainer比如说端口、上下文路径等 分析了上面两个接口原来创建 servlet 容器的工作是由 EmbeddedServletContainerFactory 完成的看下 getEmbeddedServletContainer 方法的调用栈。在 EmbeddedWebApplicationContext 中重写了 GenericWebApplicationContext#onRefresh() 方法并且调用 getEmbeddedServletContainer 方法创建 servlet 容器我们接下来分析这个创建过程。 关键代码如下省略异常处理 EmbeddedWebApplicationContext.javaOverride protected void onRefresh() {super.onRefresh();createEmbeddedServletContainer(); }private void createEmbeddedServletContainer() {EmbeddedServletContainer localContainer this.embeddedServletContainer;ServletContext localServletContext getServletContext();if (localContainer null localServletContext null) {// 从容器中获取bean如果使用tomcat则返回TomcatEmbeddedServletContainerFactoryEmbeddedServletContainerFactory containerFactory getEmbeddedServletContainerFactory();this.embeddedServletContainer containerFactory.getEmbeddedServletContainer(getSelfInitializer());}else if (localServletContext ! null) {getSelfInitializer().onStartup(localServletContext);}initPropertySources(); 我们先画出主要的流程图(查看原图) 由上图可知EmbeddedWebApplicationContext 在执行 onRefresh 方法的时候首先调用父类的 onRefresh然后从容器中获取 EmbeddedServletContainerFactory 的实现类。由于我们在 classpath 下面可以获取 tomcat 的 jar 包因此 EmbeddedServletContainerAutoConfiguration 会在 spring 容器中注册 TomcatEmbeddedServletContainerFactory 这个 bean。然后由它创建 TomcatEmbeddedServletContainer我们来看看具体的创建过程代码如下所示 TomcatEmbeddedServletContainerFactory.javaOverride public EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer… initializers) {Tomcat tomcat new Tomcat(); // 实例化 apache Tomcat File baseDir (this.baseDirectory ! null ? this.baseDirectory: createTempDir(tomcat));tomcat.setBaseDir(baseDir.getAbsolutePath());// 创建 Connector 组件默认使用org.apache.coyote.http11.Http11NioProtocolConnector connector new Connector(this.protocol); tomcat.getService().addConnector(connector);// 支持对 Connector 进行自定义设置比如设置线程池、最大连接数等customizeConnector(connector);tomcat.setConnector(connector);tomcat.getHost().setAutoDeploy(false);configureEngine(tomcat.getEngine());for (Connector additionalConnector : this.additionalTomcatConnectors) {tomcat.getService().addConnector(additionalConnector);}prepareContext(tomcat.getHost(), initializers);return getTomcatEmbeddedServletContainer(tomcat); 首先是实例化 Tomcat 对象然后创建 Connector 组件并且对 Connector 进行相关的参数设置同时也允许我们通过 TomcatConnectorCustomizer 接口进行自定义的设置。OK创建了 Tomcat 实例之后需要创建 TomcatEmbeddedServletContainer它依赖 Tomcat 对象在构造方法中便会启动 Tomcat 容器从而完成各个组件的启动流程 public TomcatEmbeddedServletContainer(Tomcat tomcat, boolean autoStart) {Assert.notNull(tomcat, Tomcat Server must not be null);this.tomcat tomcat;this.autoStart autoStart;initialize(); }private void initialize() throws EmbeddedServletContainerException {synchronized (this.monitor) {addInstanceIdToEngineName();// Remove service connectors to that protocol binding doesnt happen yetremoveServiceConnectors();// Start the server to trigger initialization listenersthis.tomcat.start();// We can re-throw failure exception directly in the main threadrethrowDeferredStartupExceptions();Context context findContext();ContextBindings.bindClassLoader(context, getNamingToken(context),getClass().getClassLoader());// Unlike Jetty, all Tomcat threads are daemon threads. We create a// blocking non-daemon to stop immediate shutdownstartDaemonAwaitThread();} Tomcat 实例的 start 方法如下所示这便回到了 tomcat 的启动流程了这里不再哆嗦了感兴趣的童鞋可以查看我的博文 Tomcat.javapublic void start() throws LifecycleException {getServer();getConnector();server.start();