引言

本篇内容源码在StandardWrapperValve的invoke方法中:

1
2
3
4
//略......
//分配一个servlet实例来处理这个请求
servlet = wrapper.allocate();
//略......

调用StandardWrapper中的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/**
* Allocate an initialized instance of this Servlet that is ready to have
* its <code>service()</code> method called. If the servlet class does
* not implement <code>SingleThreadModel</code>, the (only) initialized
* instance may be returned immediately. If the servlet class implements
* <code>SingleThreadModel</code>, the Wrapper implementation must ensure
* that this instance is not allocated again until it is deallocated by a
* call to <code>deallocate()</code>.
* 分配此Servlet的初始化实例,该实例已准备好调用其service()方法。
* 如果servlet类没有实现SingleThreadModel,则可能立即返回(only)初始化的实例。
* 如果servlet类实现了SingleThreadModel,
* 包装器实现必须确保在调用deallocate()释放该实例之前不会再次分配该实例。
*
* @exception ServletException if the servlet init() method threw
* an exception
* @exception ServletException if a loading error occurs
*/
@Override
public Servlet allocate() throws ServletException {
//如果当前正在卸载此servlet,则抛出异常
if (unloading) {
throw new ServletException(sm.getString("standardWrapper.unloading", getName()));
}
boolean newInstance = false;

// If not SingleThreadedModel, return the same instance every time
// 如果不是SingleThreadedModel,则每次返回相同的实例
// singleThreadModel:这个servlet是否实现了SingleThreadModel接口?,这个接口已经被弃用了。
// 也就是说实现了singleThreadModel接口,每次返回不同的Servlet
if (!singleThreadModel) {
// 如果需要,加载并初始化我们的实例
if (instance == null || !instanceInitialized) {
synchronized (this) {
//如果没有实例的话,加载Servlet
if (instance == null) {
try {
if (log.isDebugEnabled()) {
log.debug("Allocating non-STM instance");
}

// Note: We don't know if the Servlet implements
// SingleThreadModel until we have loaded it.
instance = loadServlet();
newInstance = true;
if (!singleThreadModel) {
// For non-STM, increment here to prevent a race
// condition with unload. Bug 43683, test case
// #3
countAllocated.incrementAndGet();
}
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("standardWrapper.allocate"), e);
}
}
//如果没有初始化的话,初始化Servlet
if (!instanceInitialized) {
initServlet(instance);
}
}
}

if (singleThreadModel) {
if (newInstance) {
// Have to do this outside of the sync above to prevent a
// possible deadlock
synchronized (instancePool) {
instancePool.push(instance);
nInstances++;
}
}
} else {
if (log.isTraceEnabled()) {
log.trace(" Returning non-STM instance");
}
// For new instances, count will have been incremented at the
// time of creation
if (!newInstance) {
countAllocated.incrementAndGet();
}
return instance;
}
}

synchronized (instancePool) {
while (countAllocated.get() >= nInstances) {
// Allocate a new instance if possible, or else wait
if (nInstances < maxInstances) {
try {
instancePool.push(loadServlet());
nInstances++;
} catch (ServletException e) {
throw e;
} catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
throw new ServletException(sm.getString("standardWrapper.allocate"), e);
}
} else {
try {
instancePool.wait();
} catch (InterruptedException e) {
// Ignore
}
}
}
if (log.isTraceEnabled()) {
log.trace(" Returning allocated STM instance");
}
countAllocated.incrementAndGet();
return instancePool.pop();
}
}


其中的loadServlet与initServlet上一篇文章分析过,这里就不看了。此方法最终返回一个Servlet实例。

鉴于这篇文章没啥东西,就一块把deallocate方法看一看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* Return this previously allocated servlet to the pool of available
* instances. If this servlet class does not implement SingleThreadModel,
* no action is actually required.
*
* @param servlet The servlet to be returned
*
* @exception ServletException if a deallocation error occurs
*/
@Override
public void deallocate(Servlet servlet) throws ServletException {

// If not SingleThreadModel, no action is required
if (!singleThreadModel) {
countAllocated.decrementAndGet();
return;
}

// Unlock and free this instance
//解锁并释放此实例
synchronized (instancePool) {
countAllocated.decrementAndGet();
instancePool.push(servlet);
instancePool.notify();
}

}

本篇结束,下一篇分析过滤器链相关代码。