SpringBoot源码阅读记录一 - 手写一个简单的Springboot

引言

在以往的spring项目中,我们的应用程序需要部署在Tomcat容器内部运行。现在Springboot将Tomcat嵌入到程序中运行,增加了应用程序的灵活性。为以后的微服务分布式打下基础。
现在来看下如何嵌入Tomcat

创建项目

创建一个简单的POM项目
在这里插入图片描述

引入Tomcat依赖

 <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>8.5.16</version>
        </dependency>

        <!-- tomcat对jsp支持 -->
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jasper</artifactId>
            <version>8.5.16</version>
        </dependency>

编写启动类

public class TomcatTest {


    public static void main(String[] args) throws ServletException, LifecycleException {
        start();
    }

    public static void start() throws ServletException, LifecycleException {
        //创建Tomcat容器和设置端口
        Tomcat tomcatServer = new Tomcat();
        tomcatServer.setPort(9001);
        tomcatServer.setBaseDir("/");

        HttpServlet httpServlet = new HttpServlet() {
            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

                resp.getWriter().print("success request!!!");
            }
        };

        System.out.println(new File("src/main").getAbsolutePath());
        StandardContext ctx = (StandardContext) tomcatServer.addWebapp("/demo", new File("src/main").getAbsolutePath());
        ctx.setReloadable(false);

        ctx.addLifecycleListener(new AprLifecycleListener(){
            @Override
            public void lifecycleEvent(LifecycleEvent event) {
                super.lifecycleEvent(event);
            }
        });


        tomcatServer.addServlet("/demo","testServlet",httpServlet);
        ctx.addServletMappingDecoded("/test.do", "testServlet");
        //启动容器
        tomcatServer.start();
        tomcatServer.getServer().await();

    }
}

测试

在这里插入图片描述

引入Spring容器


        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<!--        <dependency>-->
<!--            <groupId>org.springframework</groupId>-->
<!--            <artifactId>spring-context</artifactId>-->
<!--            <version>5.2.0.RELEASE</version>-->
<!--        </dependency>-->

<!--        &lt;!&ndash; https://mvnrepository.com/artifact/org.springframework/spring-web &ndash;&gt;-->
<!--        <dependency>-->
<!--            <groupId>org.springframework</groupId>-->
<!--            <artifactId>spring-web</artifactId>-->
<!--            <version>5.2.0.RELEASE</version>-->
<!--        </dependency>-->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>

编写spring配置

配置类

@ComponentScan("com.tomcat")
@Configuration
public class AppConfig {


    public static void main(String[] args) {

        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        System.out.println(context.getBean(MyService.class));

    }



}

自定义个Bean

@Component
public class MyService {

    @PostConstruct
    public void init(){
        System.out.println(MyService.class.getName()+"初始化");
    }

}

测试Spring

在这里插入图片描述至此Spring Tomcat 都可以独立启动了,那如何才能同时启动Spring呢,根据spi规范,Tomcat启动时会扫描包下的META-INF下service文件下
javax.servlet.ServletContainerInitializer内部定义的类。

定义回调ServletContainerInitializer

public class MyServletContainerInitializer implements ServletContainerInitializer {

    public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {

        System.out.println("我的tomcat 启动了。。。。。。。。。。");

    }
}

在这里可以引入加载Spring 容器 SpringMVC等一些相关的内容。
同样的 在Springweb下也是使用的这样的方式用来初始化spring的
在这里插入图片描述在这里插入图片描述SpringServletContainerInitializer 代码

@HandlesTypes({WebApplicationInitializer.class})
public class SpringServletContainerInitializer implements ServletContainerInitializer {
    public SpringServletContainerInitializer() {
    }

    public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
        List<WebApplicationInitializer> initializers = new LinkedList();
        Iterator var4;
        if (webAppInitializerClasses != null) {
            var4 = webAppInitializerClasses.iterator();

            while(var4.hasNext()) {
                Class<?> waiClass = (Class)var4.next();
                if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
                    try {
                        initializers.add((WebApplicationInitializer)ReflectionUtils.accessibleConstructor(waiClass, new Class[0]).newInstance());
                    } catch (Throwable var7) {
                        throw new ServletException("Failed to instantiate WebApplicationInitializer class", var7);
                    }
                }
            }
        }

        if (initializers.isEmpty()) {
            servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
        } else {
            servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
            AnnotationAwareOrderComparator.sort(initializers);
            var4 = initializers.iterator();

            while(var4.hasNext()) {
                WebApplicationInitializer initializer = (WebApplicationInitializer)var4.next();
                initializer.onStartup(servletContext);
            }

        }
    }
}

通过@HandlesTypes({WebApplicationInitializer.class})引入WebApplicationInitializer对象并且调用WebApplicationInitializer->onStartup(方法)

实现AbstractAnnotationConfigDispatcherServletInitializer

回调类

public class SpringServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {




    @Override
    protected Class<?>[] getRootConfigClasses() {
        System.out.println("-----------------------------");
        return new Class[]{};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

配置类

@ComponentScan("com.tomcat.mvc")
@Configuration
public class WebConfig implements WebMvcConfigurer {

}

注册Bean

@RestController
public class MyController {


    @GetMapping("/index")
    public String getIndex(){


        return "this is CustomSpringBoot index";
    }

}

测试

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值