实习记录2 springboot应用中启动tomcat容器

本文通过一个具体的例子分析了在SpringBoot应用中,由于启动顺序不同,导致在Servlet中使用@Autowired注解的属性可能出现NullPointerException。在Spring容器启动过程中,异步任务尝试获取bean时,由于Servlet实例未完成初始化,导致获取ServletContext时发生NPE。通过源码跟踪,揭示了SpringBoot启动web服务器前会先初始化所有bean,而Servlet实例化和配置是在web服务器启动时完成的。解决方法是调整Servlet的loadOnStartup参数。
摘要由CSDN通过智能技术生成

在过去spring还没有统治java的时候,spring容器的启动通常是在webapp中的xml文件中配置服务器启动监听器,然后在监听器中启动spring容器。但是现在大多数的web应用开发会选择基于spring-boot开发,这时主次顺序就变成了先启动spring的容器,等spring容器刷新得差不多了,才会来启动web容器。这种启动顺序的差异就很有可能带来一些差错。在前几天的看到同事的代码,便发现了这类似的错误。废话不多说。直接上代码

@Configuration
class MainConfig {
    @Bean
    public Object bean() {
        return "i am a bean";
    }
}

@Component
@WebServlet("/task")
public class BadTaskServlet extends HttpServlet {

    @Qualifier("bean")
    @Autowired
    private Object bean;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        initBean();
        resp.getOutputStream().write(Integer.parseInt("123"));
    }


    private Object initBean() {
        if (bean == null) {
            bean = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
        }
        return bean;
    }

    @Scheduled(cron = "*/5 * * * * ?")
    public void task() {
        initBean();
        System.out.println(bean);
    }

}

这个写法错误的一点在于initBean这个方法这里。简单地描述一下这个场景,1. 这里是打算做一个durid的监控类,这个监控的页面很简单,只需要实现一个Servlet的类就可以了。2. 但是与此同时,在这个监控的页面还跑了一个定时任务,定时任务的目的是打算定时清楚redis中的数据。 我在这里就忽略了其他的不重要的部分,直接上关键的点吗的部分!

这位同事认为这个spring的注入并不一定会生效,当容器中没有实例的时候bean就会为null。但是其实在使用@Autowired注解之后,默认情况下,在容器查找不到一个实例的时候时候,那么就会直接抛出一个找不到bean的异常,因此这个bean如果为null的话,其实这个应用是直接启动不起来的!

于是这里,代码中initBean的方法就打算在查找不到bean的时候,手动地获取一个bean。但是问题就出现在了WebApplicationContextUtils.getWebApplicationContext(getServletContext()).getBean(“bean”);;这个方法是打算通过Servlet的容器上下文来获取spring的上下文,然后再通过这个方法来手动获取bean。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值