KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > aop > target > ThreadLocalTargetSource


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.aop.target;
18
19 import java.util.Collections JavaDoc;
20 import java.util.HashSet JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.Set JavaDoc;
23
24 import org.springframework.aop.IntroductionAdvisor;
25 import org.springframework.aop.support.DefaultIntroductionAdvisor;
26 import org.springframework.aop.support.DelegatingIntroductionInterceptor;
27 import org.springframework.beans.BeansException;
28 import org.springframework.beans.factory.DisposableBean;
29
30 /**
31  * Alternative to an object pool. This TargetSource uses a threading model in which
32  * every thread has its own copy of the target. There's no contention for targets.
33  * Target object creation is kept to a minimum on the running server.
34  *
35  * <p>Application code is written as to a normal pool; callers can't assume they
36  * will be dealing with the same instance in invocations in different threads.
37  * However, state can be relied on during the operations of a single thread:
38  * for example, if one caller makes repeated calls on the AOP proxy.
39  *
40  * <p>Cleanup of thread-bound objects is performed on BeanFactory destruction,
41  * calling their <code>DisposableBean.destroy()</code> method if available.
42  * Be aware that many thread-bound objects can be around until the application
43  * actually shuts down.
44  *
45  * @author Rod Johnson
46  * @author Juergen Hoeller
47  * @author Rob Harrop
48  * @see ThreadLocalTargetSourceStats
49  * @see org.springframework.beans.factory.DisposableBean#destroy()
50  */

51 public class ThreadLocalTargetSource extends AbstractPrototypeBasedTargetSource
52         implements ThreadLocalTargetSourceStats, DisposableBean {
53     
54     /**
55      * ThreadLocal holding the target associated with the current
56      * thread. Unlike most ThreadLocals, which are static, this variable
57      * is meant to be per thread per instance of the ThreadLocalTargetSource class.
58      */

59     private final ThreadLocal JavaDoc targetInThread = new ThreadLocal JavaDoc();
60
61     /**
62      * Set of managed targets, enabling us to keep track of the targets we've created.
63      */

64     private final Set JavaDoc targetSet = Collections.synchronizedSet(new HashSet JavaDoc());
65     
66     private int invocationCount;
67     
68     private int hitCount;
69
70
71     /**
72      * Implementation of abstract getTarget() method.
73      * We look for a target held in a ThreadLocal. If we don't find one,
74      * we create one and bind it to the thread. No synchronization is required.
75      */

76     public Object JavaDoc getTarget() throws BeansException {
77         ++this.invocationCount;
78         Object JavaDoc target = this.targetInThread.get();
79         if (target == null) {
80             if (logger.isDebugEnabled()) {
81                 logger.debug("No target for prototype '" + getTargetBeanName() + "' bound to thread: " +
82                     "creating one and binding it to thread '" + Thread.currentThread().getName() + "'");
83             }
84             // Associate target with ThreadLocal.
85
target = newPrototypeInstance();
86             this.targetInThread.set(target);
87             this.targetSet.add(target);
88         }
89         else {
90             ++this.hitCount;
91         }
92         return target;
93     }
94     
95     /**
96      * Dispose of targets if necessary; clear ThreadLocal.
97      * @see #destroyPrototypeInstance
98      */

99     public void destroy() {
100         logger.debug("Destroying ThreadLocalTargetSource bindings");
101         synchronized (this.targetSet) {
102             for (Iterator JavaDoc it = this.targetSet.iterator(); it.hasNext(); ) {
103                 destroyPrototypeInstance(it.next());
104             }
105             this.targetSet.clear();
106         }
107         // Clear ThreadLocal, just in case.
108
this.targetInThread.set(null);
109     }
110
111
112     public int getInvocationCount() {
113         return this.invocationCount;
114     }
115
116     public int getHitCount() {
117         return this.hitCount;
118     }
119
120     public int getObjectCount() {
121         return this.targetSet.size();
122     }
123
124
125     /**
126      * Return an introduction advisor mixin that allows the AOP proxy to be
127      * cast to ThreadLocalInvokerStats.
128      */

129     public IntroductionAdvisor getStatsMixin() {
130         DelegatingIntroductionInterceptor dii = new DelegatingIntroductionInterceptor(this);
131         return new DefaultIntroductionAdvisor(dii, ThreadLocalTargetSourceStats.class);
132     }
133
134 }
135
Popular Tags