Java Web中的Filter与Struts中的Interceptor到底是不是单例的?
答案首先是,它们都是单例的。下面我就从源码角度去解释为什么是单例的。
首先我们先对Interceptor进行分析,在分析之前我们先假设Filter是单例的,然后再开始。对Filter是不是单例的的源码分析会稍后补上,其实Filter是不是单例我们从它的方法也可以看到出来,因为它有init的方法,init方法只执行一次,所以我们猜测它是单例的,否则每次加载Filter都应该执行init进行初始化。
好,我们既然假设了Filter是单例的,我们又知道Struts的入口就是一个Filter,它是在init中进行初始化,所以可以看出,那我们可以知道Struts本身应该只初始化一次,也是单例的。但是Struts本身是单例和Struts框架中包含的各种对象是不是单例的并没有直接关系,所以这时候Interceptor是不是单例的我们依旧无法得知。好,那现在我们去看Interceptor源码。
拦截器在Struts中可以说是功能强大,但是我没用到,呵呵。实现拦截器有两种方法,一个是继承一个抽象类AbstractInterceptor,实现抽象方法;而另一个是实现接口Interceptor的所有方法。其实差不多,相差的地方还是在抽象类与接口本身的区别;而且该抽象类其实也是实现了Interceptor接口。我们假设采用第一种方法,可以看到抽象基类中已经给我们实现了两个方法,虽然什么都没做,但是确实是实现了。
public abstract class AbstractInterceptor implements Interceptor {
/**
* Does nothing
*/
public void init() { }
/**
* Does nothing
*/
public void destroy() {}
/**
* Override to handle interception
*/
public abstract String intercept(ActionInvocation invocation) throws Exception;
}
好,看到上述源码也有init的方法,那这个时候我们是否可以猜测拦截器是单例的那。下面我们就开始分析,拦截器到底是不是单例的那。那我们要从哪里开始分析那,要去看源码应该看那一部分的源码那。我们知道拦截器必须在xml中声明配置,所以我们应该看和读取配置有关的源码;那Struts读取配置的源码在哪里啊;这个时候我们又知道Struts的入口是个Filter,对于Filter都有一个init方法,而Struts又都是基于xml或者注解进行配置的,那我们猜测读取配置进行初始化工作应该是在init的方法中。那我们就开始对init方法进行分析:
public void init(FilterConfig filterConfig) throws ServletException {
InitOperations init = new InitOperations();
try {
FilterHostConfig config = new FilterHostConfig(filterConfig);
init.initLogging(config);
Dispatcher dispatcher = init.initDispatcher(config);
init.initStaticContentLoader(config, dispatcher);
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
postInit(dispatcher, filterConfig);
} finally {
init.cleanup();
}
}
可以看到代码如上,根