项目结构搭建
新建一个空项目
建立一个模块
新建注解,和启动类
建立第二个模块
导入spring-web依赖,
使用自定义的bootstart类方法启动。
将服务器启动方法抽象为接口
实现两个实现类,模拟服务器的启动
模拟实现条件注解
具体逻辑为,拿到@HuwenConditionalOnClass中的value属性,然后用类加载器进行加载,如果加载到了所指定的这个类,那就表示符合条件,如果加载不到,则表示不符合条件。
模拟实现自动配置类
这个代码还是比较简单的,通过一个WebServiceAutoConfiguration的Spring配置类,在里面定义了两个Bean,一个TomcatWebServer,一个JettyWebServer,不过这两个要生效的前提是符合当前所指定的条件,比如:
- 只有存在"org.apache.catalina.startup.Tomcat"类,那么才有TomcatWebServer这个Bean
- 只有存在"org.eclipse.jetty.server.Server"类,那么才有TomcatWebServer这个Bean
并且我们只需要在ZhouyuSpringApplication中getWebServer方法,如此实现:
这样整体SpringBoot启动逻辑就是这样的:
- 创建一个AnnotationConfigWebApplicationContext容器
- 解析MyApplication类,然后进行扫描
- 通过getWebServer方法从Spring容器中获取WebServer类型的Bean
- 调用WebServer对象的start方法
有了以上步骤,我们还差了一个关键步骤,就是Spring要能解析到WebServiceAutoConfiguration这个自动配置类,因为不管这个类里写了什么代码,Spring不去解析它,那都是没用的,此时我们需要SpringBoot在run方法中,能找到WebServiceAutoConfiguration这个配置类并添加到Spring容器中。
MyApplication是Spring的一个配置类,但是MyApplication是我们传递给SpringBoot,从而添加到Spring容器中去的,而WebServiceAutoConfiguration就需要SpringBoot去自动发现,而不需要程序员做任何配置才能把它添加到Spring容器中去,而且要注意的是,Spring容器扫描也是扫描不到WebServiceAutoConfiguration这个类的,因为我们的扫描路径是"com.zhouyu.user",而WebServiceAutoConfiguration所在的包路径为"com.zhouyu.springboot"。
那SpringBoot中是如何实现的呢?通过SPI,当然SpringBoot中自己实现了一套SPI机制,也就是我们熟知的spring.factories文件,那么我们模拟就不搞复杂了,就直接用JDK自带的SPI机制。
发现自动配置类
SPI的配置就完成了,相当于通过com.zhouyu.springboot.AutoConfiguration文件配置了springboot中所提供的配置类。
并且提供一个接口:
jdk的spi根据这个顶层接口,查找配置类
实现这个配置类接口
然后我们再利用spring中的@Import技术来导入这些配置类,
seletor类实现为
返回配置类的类名