从零开始学机器学习——K-Means 聚类
文章链接:从零开始学机器学习——K-Means 聚类-腾讯云开发者社区-腾讯云
推荐原因:介绍了聚类算法的使用,使用聚类算法中的经典方法——k-means,对数据进行训练和预测。
Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories
文件的解析源码API机制。
Spring Boot是由Pivotal团队开发的一个框架,它基于Spring框架,旨在简化Spring应用的开发和部署。Spring Boot最早于2014年发布,其设计初衷是为了应对复杂的企业级应用开发中频繁出现的配置冗余和重复代码问题。
Spring Boot的发展历程可以分为几个关键阶段:
Spring Boot的核心特点可以概括为以下几点:
Spring Boot适用于多种业务场景,包括但不限于:
Spring Boot的功能点非常丰富,以下是一些关键功能点:
Spring Boot的自动配置机制是其核心特性之一。它通过@EnableAutoConfiguration
注解实现,根据类路径中的依赖自动配置合适的Spring组件。自动配置的实现主要依赖于SpringFactoriesLoader
类和@EnableAutoConfiguration
注解。
在Spring Boot启动时,SpringFactoriesLoader
会扫描类路径下的META-INF/spring.factories
文件,加载其中定义的自动配置类。每个自动配置类都会根据一定的条件(如类路径中是否存在特定的类或Bean)来决定是否生效。
spring.factories
文件解析源码API机制spring.factories
文件是Spring Boot自动配置机制的关键组成部分。它位于类路径下的META-INF
目录中,用于定义Spring Boot的自动配置类和其他扩展点。
spring.factories
文件的结构spring.factories
文件是一个简单的属性文件,其结构如下:
properties复制代码
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.autoconfigure.MyAutoConfiguration
每一行定义了一个扩展点的接口名称和对应的实现类名称,多个实现类之间用逗号分隔。
SpringFactoriesLoader
类的解析机制SpringFactoriesLoader
类是Spring Boot用于加载spring.factories
文件中定义的类的工具类。其主要方法loadFactories
用于加载指定接口的所有实现类:
java复制代码
public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
try {
Enumeration<URL> urls = (classLoader != null ? classLoader.getResources("META-INF/spring.factories") :
ClassLoader.getSystemResources("META-INF/spring.factories"));
List<String> factoryNames = new ArrayList<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
String factoryNamesProperty = properties.getProperty(factoryClassName);
for (String factoryName : StringUtils.commaDelimitedListToStringArray(factoryNamesProperty)) {
factoryNames.add(factoryName.trim());
}
}
return instantiateFactories(factoryClass, factoryNames, classLoader);
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
"META-INF/spring.factories"]", ex);
}
}
该方法首先通过classLoader.getResources
方法找到所有META-INF/spring.factories
文件的URL,然后逐个加载这些文件的内容,解析出指定接口的所有实现类名称,最后通过反射创建这些类的实例并返回。
Spring Boot内置了Tomcat、Jetty或Undertow等服务器,使应用可以直接运行在这些服务器上,无需外部容器。内嵌服务器的实现原理主要包括以下几个步骤:
spring-boot-starter-web
依赖,则默认使用Tomcat服务器。
EmbeddedServletContainerFactory
接口及其实现类来管理内嵌服务器的创建和启动过程。
为了更深入地理解Spring Boot的启动过程,我们可以通过Java代码手写模拟Spring Boot的启动过程。以下是一个简单的模拟实现:
首先,我们定义一个自定义的注解@ZhouyuSpringBootApplication
,用于标识Spring Boot应用的启动类:
java复制代码
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public @interface ZhouyuSpringBootApplication {
}
然后,我们定义一个配置类WebConfig
,用于配置Spring MVC和视图解析器:
java复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.example.controller")
public class WebConfig implements WebMvcConfigurer {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
接下来,我们创建一个自定义的SpringApplication
类,用于启动Spring Boot应用:
java复制代码
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
public class ZhouyuSpringApplication {
public static void run(Class<?> primarySource, String... args) {
ConfigurableApplicationContext context = SpringApplication.run(primarySource, args);
context.close();
}
}
最后,我们创建一个启动类MyApp
,并使用@ZhouyuSpringBootApplication
注解进行标注:
java复制代码
import com.example.config.WebConfig;
import com.example.boot.ZhouyuSpringBootApplication;
@ZhouyuSpringBootApplication
public class MyApp {
public static void main(String[] args) {
ZhouyuSpringApplication.run(MyApp.class, args);
}
}
spring.factories
文件的解析为了模拟spring.factories
文件的解析过程,我们可以创建一个工具类SpringFactoriesLoader
,用于加载指定接口的所有实现类:
java复制代码
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
public class SpringFactoriesLoader {
public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) throws IOException {
String factoryClassName = factoryClass.getName();
List<String> factoryNames = new ArrayList<>();
Enumeration<URL> urls = classLoader.getResources("META-INF/spring.factories");
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
try (InputStream is = url.openStream()) {
Properties properties = new Properties();
properties.load(is);
String factoryNamesProperty = properties.getProperty(factoryClassName);
for (String factoryName : factoryNamesProperty.split(",")) {
factoryNames.add(factoryName.trim());
}
}
}
List<T> factories = new ArrayList<>();
for (String factoryName : factoryNames) {
try {
Class<?> factoryClass = Class.forName(factoryName, true, classLoader);
T factory = (T) factoryClass.getDeclaredConstructor().newInstance();
factories.add(factory);
} catch (Exception e) {
throw new IllegalArgumentException("Unable to instantiate factory class: " + factoryName, e);
}
}
return factories;
}
}
然后,我们可以在启动类中使用这个工具类来加载并注册自动配置类:
java复制代码
import com.example.config.WebConfig;
import com.example.boot.ZhouyuSpringBootApplication;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import java.util.List;
@ZhouyuSpringBootApplication
public class MyApp {
public static void main(String[] args) throws IOException {
List<ConfigurationClassPostProcessor> postProcessors = SpringFactoriesLoader.loadFactories(
ConfigurationClassPostProcessor.class, MyApp.class.getClassLoader());
// 注册自动配置类
for (ConfigurationClassPostProcessor postProcessor : postProcessors) {
// 这里可以添加逻辑来注册自动配置类
}
ZhouyuSpringApplication.run(MyApp.class, args);
}
}
需要注意的是,上述代码只是一个简单的模拟实现,并没有完全覆盖Spring Boot的启动过程和自动配置机制的所有细节。在实际应用中,Spring Boot的启动过程和自动配置机制要复杂得多,涉及多个组件和类的协同工作。
本文通过深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,使读者对Spring Boot有了更深入的了解。同时,通过手写模拟Spring Boot的启动过程,特别是spring.factories
文件的解析源码API机制,使读者能够更直观地理解Spring Boot的自动配置机制。希望本文能够为读者在实际应用中更好地使用Spring Boot提供有益的参考和帮助。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。