h5特效网站欣赏,新手学做网站用什么软件,广州市花,长春市建设技工学校网站前言 首先确定springboot在spring基础上主要做了哪些改动#xff1a;内嵌tomcatspi技术动态加载
一、基本实现
1. 建一个工程目录结构如下#xff1a;
springboot: 源码实现逻辑
user : 业务系统2.springboot工程项目构建
1. pom依赖如下 dependencies内嵌tomcatspi技术动态加载
一、基本实现
1. 建一个工程目录结构如下
springboot: 源码实现逻辑
user : 业务系统2.springboot工程项目构建
1. pom依赖如下 dependenciesdependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.3.18/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-web/artifactIdversion5.3.18/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-webmvc/artifactIdversion5.3.18/version/dependencydependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion4.0.1/version/dependencydependencygroupIdorg.apache.tomcat.embed/groupIdartifactIdtomcat-embed-core/artifactIdversion9.0.60/version/dependency/dependencies2. SpringBoot时核心会用到SpringBoot一个类和注解
SpringBootApplication这个注解是加在应用启动类上的也就是main方法所在的类SpringApplication这个类中有个run()方法用来启动SpringBoot应用的.
下面一一实现 Retention(RetentionPolicy.RUNTIME)Target(ElementType.TYPE)ConfigurationComponentScanImport(KcImportSelect.class)
public interface KcSpringBootApplication {}public class KcSpringApplication {public static AnnotationConfigWebApplicationContext run(Class cls){/*** spring启动步骤* 1、构建上下文对象* 2、注册配置类* 3、刷新容器*/AnnotationConfigWebApplicationContext contextnew AnnotationConfigWebApplicationContext();context.register(cls);context.refresh();/*** 内嵌tomcat\jetty 启动*/WebServer webServergetWebServer(context);webServer.start();return context;}/*** 获取服务有可能tomcat\jetty或者其他服务器* param context* return*/public static WebServer getWebServer(AnnotationConfigWebApplicationContext context){MapString, WebServer beansOfType context.getBeansOfType(WebServer.class);if(beansOfType.isEmpty()||beansOfType.size()1){throw new NullPointerException();}return beansOfType.values().stream().findFirst().get();}}
3.内嵌tomcat、jetty服务器实现
项目根据pom配置动态实现tomcat\jetty内嵌要求如下
如果项目中有Tomcat的依赖那就启动Tomcat如果项目中有Jetty的依赖就启动Jetty如果两者都没有则报错如果两者都有也报错
首先定义服务接口WebServer
public interface WebServer {void start() ;
}tomcat服务实现
public class TomcatWebServer implements WebServer {private Tomcat tomcat;public TomcatWebServer(WebApplicationContext webApplicationContext) {tomcat new Tomcat();Server server tomcat.getServer();Service service server.findService(Tomcat);Connector connector new Connector();connector.setPort(8081);Engine engine new StandardEngine();engine.setDefaultHost(localhost);Host host new StandardHost();host.setName(localhost);String contextPath ;Context context new StandardContext();context.setPath(contextPath);context.addLifecycleListener(new Tomcat.FixContextListener());host.addChild(context);engine.addChild(host);service.setContainer(engine);service.addConnector(connector);tomcat.addServlet(contextPath, dispatcher, new DispatcherServlet(webApplicationContext));context.addServletMappingDecoded(/*, dispatcher);}Overridepublic void start() {try {System.out.println(tomcat start......);tomcat.start();}catch (Exception e){e.printStackTrace();}}
}jetty服务实现具体实现逻辑没写具体实现逻辑类似tomcat实现
public class JettyWebServer implements WebServer{Overridepublic void start() {System.out.println(jetty start......);}
}思考jetty\tomcat都已实现总不能用if/else这样决定用哪个服务扩展性太差基于此就联想到spring的Condition条件注解和参考springboot中的OnClassCondition这个注解。
具体实现如下
public class KcOnClassCondition implements Condition {Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {MapString, Object annotationAttributes metadata.getAnnotationAttributes(KcConditionalOnClass.class.getName());String value (String) annotationAttributes.get(value);try {context.getClassLoader().loadClass(value);} catch (ClassNotFoundException e) {return false;}return true;}
}Configuration
public class WebServerConfiguration{BeanKcConditionalOnClass(org.apache.catalina.startup.Tomcat)public TomcatWebServer tomcatWebServer( WebApplicationContext webApplicationContext){return new TomcatWebServer(webApplicationContext);}BeanKcConditionalOnClass(org.eclipse.jetty.server.Server)public JettyWebServer jettyWebServer(){return new JettyWebServer();}
}至此springboot简化版已实现完成首先启动看看
4.基于JDK的SPI实现扫描AutoConfiguration接口
AutoConfiguration接口
public interface AutoConfiguration {
}
实现DeferredImportSelector接口实现类具体为什么实现Import这个接口请看以前的文章主要这个接口具有延迟功能
public class KcImportSelect implements DeferredImportSelector {Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {ServiceLoaderAutoConfiguration load ServiceLoader.load(AutoConfiguration.class);ListString list new ArrayList();for (AutoConfiguration autoConfiguration : load) {list.add(autoConfiguration.getClass().getName());}return list.toArray(new String[0]);}
}即KcSpringBootApplication注解导入该配置类 Retention(RetentionPolicy.RUNTIME)Target(ElementType.TYPE)ConfigurationComponentScanImport(KcImportSelect.class)
public interface KcSpringBootApplication {}WebServerConfiguration实现AutoConfiguration接口
Configuration
public class WebServerConfiguration implements AutoConfiguration{BeanKcConditionalOnClass(org.apache.catalina.startup.Tomcat)public TomcatWebServer tomcatWebServer( WebApplicationContext webApplicationContext){return new TomcatWebServer(webApplicationContext);}BeanKcConditionalOnClass(org.eclipse.jetty.server.Server)public JettyWebServer jettyWebServer(){return new JettyWebServer();}
}在springboot项目下创建META-INFO/service 接口全路径命名的文件文件内容接口实现类全路径
至此springboot简易版已全部实现。
二、应用业务系统引入自己构建的springboot
1、user项目的pom依赖引入自己构建的springboot项目 dependenciesdependencygroupIdcom.kc/groupIdartifactIdspringboot/artifactIdversion1.0-SNAPSHOT/version/dependency/dependencies2、启动类
ComponentScan(basePackages {kc.*})KcSpringBootApplication
public class UserApplication {public static void main(String[] args) {AnnotationConfigWebApplicationContext run KcSpringApplication.run(UserApplication.class);System.out.println(run.getBeanFactory());}
}3、实现具体业务类
RestController
public class UserController {Autowiredprivate UserService userService;GetMapping(test)public String test() {return userService.test();}
}Service
public class UserService {public String test() {return hello springboot;}
}
4、启动测试访问 三、项目地址
git地址