今天在看《看透 Spring MVC 源代码分析与实践》一书的 【6.2 GenericServlet】 这个章节的时候,有几段话是这么说的:
GenericServlet 实现了 Servlet 的 init(ServletConfig config) 方法,在里面将 config 设置给了内部变量 config,然后调用了无参的 init() 方法,这个方法是个模板方法,在子类中可以通过覆盖它来完成自己的初始化工作,代码如下:
// javax.servlet.GenericServlet
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
}
这种做法有三个作用:首先,将参数 config 设置给了内部属性 config,这样就可以在 ServletConfig 的接口方法中直接调用 config 的相应方法来执行;其次,这么做之后我们在写 Servlet 的时候就可以只处理自己的初始化逻辑,而不需要再关心 config 了;还有一个作用就是在重写 init 方法时也不需要再调用 super.init(config)了。如果在自己的 Servlet 中重写了带参数的 init 方法,那么一定要记着调用 super.init(config),否则这里的 config 就接收不到值,相应的 ServletConfig 方法也就不能执行了。
请问,“还有一个作用就是在重写 init 方法时也不需要再调用 super.init(config)了。如果在自己的 Servlet 中重写了带参数的 init 方法,那么一定要记着调用 super.init(config),否则这里的 config 就接收不到值,相应的 ServletConfig 方法也就不能执行了”怎么理解?
這是
Java
多态的特性,如果目标类型重写了父类的方法,那么在执行时会执行目标类型的方法。换句话说如果你重写了init(ServletConfig config)
,那么Servlet
在初始化的时候会执行你重写的函数,而不会执行GenericServlet
的函数,那么GenericServlet.config
也不会初始化。config
未初始化时,如果你调用了父类提供的方法如getServletContext()/getInitParameter("k")
都将会得到IllegalStateException
异常。所以需要显示的执行
super.init(config)
,当然最好的做法是选择重写init()
方法而不是init(ServletConfig config)
方法。