Package org.springframework.aop.target

Source Code of org.springframework.aop.target.ThreadLocalTargetSource

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

package org.springframework.aop.target;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.springframework.aop.IntroductionAdvisor;
import org.springframework.aop.support.DefaultIntroductionAdvisor;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.core.NamedThreadLocal;

/**
* Alternative to an object pool. This TargetSource uses a threading model in which
* every thread has its own copy of the target. There's no contention for targets.
* Target object creation is kept to a minimum on the running server.
*
* <p>Application code is written as to a normal pool; callers can't assume they
* will be dealing with the same instance in invocations in different threads.
* However, state can be relied on during the operations of a single thread:
* for example, if one caller makes repeated calls on the AOP proxy.
*
* <p>Cleanup of thread-bound objects is performed on BeanFactory destruction,
* calling their <code>DisposableBean.destroy()</code> method if available.
* Be aware that many thread-bound objects can be around until the application
* actually shuts down.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author Rob Harrop
* @see ThreadLocalTargetSourceStats
* @see org.springframework.beans.factory.DisposableBean#destroy()
*/
public class ThreadLocalTargetSource extends AbstractPrototypeBasedTargetSource
    implements ThreadLocalTargetSourceStats, DisposableBean {
 
  /**
   * ThreadLocal holding the target associated with the current
   * thread. Unlike most ThreadLocals, which are static, this variable
   * is meant to be per thread per instance of the ThreadLocalTargetSource class.
   */
  private final ThreadLocal<Object> targetInThread =
      new NamedThreadLocal<Object>("Thread-local instance of bean '" + getTargetBeanName() + "'");

  /**
   * Set of managed targets, enabling us to keep track of the targets we've created.
   */
  private final Set<Object> targetSet = Collections.synchronizedSet(new HashSet<Object>());
 
  private int invocationCount;
 
  private int hitCount;


  /**
   * Implementation of abstract getTarget() method.
   * We look for a target held in a ThreadLocal. If we don't find one,
   * we create one and bind it to the thread. No synchronization is required.
   */
  public Object getTarget() throws BeansException {
    ++this.invocationCount;
    Object target = this.targetInThread.get();
    if (target == null) {
      if (logger.isDebugEnabled()) {
        logger.debug("No target for prototype '" + getTargetBeanName() + "' bound to thread: " +
            "creating one and binding it to thread '" + Thread.currentThread().getName() + "'");
      }
      // Associate target with ThreadLocal.
      target = newPrototypeInstance();
      this.targetInThread.set(target);
      this.targetSet.add(target);
    }
    else {
      ++this.hitCount;
    }
    return target;
  }
 
  /**
   * Dispose of targets if necessary; clear ThreadLocal.
   * @see #destroyPrototypeInstance
   */
  public void destroy() {
    logger.debug("Destroying ThreadLocalTargetSource bindings");
    synchronized (this.targetSet) {
      for (Object target : this.targetSet) {
        destroyPrototypeInstance(target);
      }
      this.targetSet.clear();
    }
    // Clear ThreadLocal, just in case.
    this.targetInThread.remove();
  }


  public int getInvocationCount() {
    return this.invocationCount;
  }

  public int getHitCount() {
    return this.hitCount;
  }

  public int getObjectCount() {
    return this.targetSet.size();
  }


  /**
   * Return an introduction advisor mixin that allows the AOP proxy to be
   * cast to ThreadLocalInvokerStats.
   */
  public IntroductionAdvisor getStatsMixin() {
    DelegatingIntroductionInterceptor dii = new DelegatingIntroductionInterceptor(this);
    return new DefaultIntroductionAdvisor(dii, ThreadLocalTargetSourceStats.class);
  }

}
TOP

Related Classes of org.springframework.aop.target.ThreadLocalTargetSource

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.