读源码学Servlet(4)关于覆盖GenericServlet的Init()方法
之前提到servlet 生命周期中的三个阶段,第一个阶段中servlet容器会执行init方法来初始化一个servlet.
init方法和destroy这两个方法在servlet生命周期中之执行一次。servlet容器(或者说是servlet引擎)创建了servlet实例对象后立即调用该init方法。
Init方法是在servlet对象被创建后,再由servlet容器调用的方法,其执行位于构造方法之后,在执行init方法时,会传递一个serveltConfig对象。
所以,如果要在初始代码中用到servletConfig对象,则这些初始操作只能在init方法中编写,不能在构造方法中编写.
GenericServlet中关于init方法的示意源码:
public void init(ServletConfig config) throws ServletException
{
this.config=config;
......
}
如果在要在自己编写的servlet类中增加一些额外的初始化功能,则必须覆盖GenricServlet类的init(ServletConfig config)方法,如果覆盖后,父类的init(ServletConfig config)方法就不会被调用。GenericServlet类中有些方法依赖init方法执行的结果,例如
getServletName()方法:
public ServletContext getServeltContext()
{
return config.getServletContext;
}
这里的config对象的引用就来自Init(ServletConfig config)执行的结果.
所以如果子类需要覆盖了父类的init(ServletConfig config)方法,则首先要调用父类的init(ServletConfig config)方法,也就是先加入 super.init(config) 语句来先执行父类的方法.否则,会产生空指针异常 java.lang.NullPointerException ,因为config对象的引用为空。
为了避免这样的情况的产生,GenericServlet的设计人员 在GenericServlet中又定义了一个无参数的init()空方法. 且在init(servletConfig config)方法最后也调用了这个无参的空方法
public void init(ServletConfig config) throws ServletException
{
this.config=config;
init();
}
所以,我们只需覆盖这个无参的init方法加入自己的初始代码即可,而无需覆盖带参数的父类的init方法.
如果有多个重载的init方法,对以servlet而言,servlet容器始终就之调用servlet接口中的那个方法:init(ServletConfig config) (当然也会执行已经覆盖的无参的init()方法),其他的覆盖的init方法不会执行。
分析 2中关于servlet生命周期的那个例子程序中的一个代码:
//覆盖父类的init(ServletConfig config)方法 加入计数
public void init(ServletConfig config) throws ServletException
{
super.init(config); //调用父类的init方法
name=config.getServletName();
initvar++;
System.out.println(name+">init():Servlet 被初始化了"+initvar+"次");
}
/* 父类的带参数的init(ServletConfig config)方法最终还是会调用了不带参数的init()方法,
* 所以也可以在自己的servlet中覆盖不带参数的init()方法来加入自己的统计参数代码
*/
public void init() //覆盖父类的不带参数的初始化方法
{
//name=getServleConfig.getServletNmae(); //因为已经实现了servletConfig接口,则直接调用其方法即可
name=getServletName(); //直接返回
initvar++;
System.out.println(name+"init(): servlet被初始化了了 "+initvar+"次");
}
以上的功能是一样的。
下一篇: 世界再一次被我拯救