/* * Copyright 2002-2016 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 org.apache.commons.pool2.ObjectPool; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.PooledObjectFactory; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; /** * {@link org.springframework.aop.TargetSource} implementation that holds * objects in a configurable Apache Commons2 Pool. * * <p>By default, an instance of {@code GenericObjectPool} is created. * Subclasses may change the type of {@code ObjectPool} used by * overriding the {@code createObjectPool()} method. * * <p>Provides many configuration properties mirroring those of the Commons Pool * {@code GenericObjectPool} class; these properties are passed to the * {@code GenericObjectPool} during construction. If creating a subclass of this * class to change the {@code ObjectPool} implementation type, pass in the values * of configuration properties that are relevant to your chosen implementation. * * <p>The {@code testOnBorrow}, {@code testOnReturn} and {@code testWhileIdle} * properties are explicitly not mirrored because the implementation of * {@code PoolableObjectFactory} used by this class does not implement * meaningful validation. All exposed Commons Pool properties use the * corresponding Commons Pool defaults. * * <p>Compatible with Apache Commons Pool 2.4, as of Spring 4.2. * * @author Rod Johnson * @author Rob Harrop * @author Juergen Hoeller * @author Stephane Nicoll * @author Kazuki Shimizu * @since 4.2 * @see GenericObjectPool * @see #createObjectPool() * @see #setMaxSize * @see #setMaxIdle * @see #setMinIdle * @see #setMaxWait * @see #setTimeBetweenEvictionRunsMillis * @see #setMinEvictableIdleTimeMillis */ @SuppressWarnings({"rawtypes", "unchecked", "serial"}) public class CommonsPool2TargetSource extends AbstractPoolingTargetSource implements PooledObjectFactory<Object> { private int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE; private int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE; private long maxWait = GenericObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS; private long timeBetweenEvictionRunsMillis = GenericObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; private long minEvictableIdleTimeMillis = GenericObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; private boolean blockWhenExhausted = GenericObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED; /** * The Apache Commons {@code ObjectPool} used to pool target objects */ private ObjectPool pool; /** * Create a CommonsPoolTargetSource with default settings. * Default maximum size of the pool is 8. * @see #setMaxSize * @see GenericObjectPoolConfig#setMaxTotal */ public CommonsPool2TargetSource() { setMaxSize(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL); } /** * Set the maximum number of idle objects in the pool. * Default is 8. * @see GenericObjectPool#setMaxIdle */ public void setMaxIdle(int maxIdle) { this.maxIdle = maxIdle; } /** * Return the maximum number of idle objects in the pool. */ public int getMaxIdle() { return this.maxIdle; } /** * Set the minimum number of idle objects in the pool. * Default is 0. * @see GenericObjectPool#setMinIdle */ public void setMinIdle(int minIdle) { this.minIdle = minIdle; } /** * Return the minimum number of idle objects in the pool. */ public int getMinIdle() { return this.minIdle; } /** * Set the maximum waiting time for fetching an object from the pool. * Default is -1, waiting forever. * @see GenericObjectPool#setMaxWaitMillis */ public void setMaxWait(long maxWait) { this.maxWait = maxWait; } /** * Return the maximum waiting time for fetching an object from the pool. */ public long getMaxWait() { return this.maxWait; } /** * Set the time between eviction runs that check idle objects whether * they have been idle for too long or have become invalid. * Default is -1, not performing any eviction. * @see GenericObjectPool#setTimeBetweenEvictionRunsMillis */ public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) { this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; } /** * Return the time between eviction runs that check idle objects. */ public long getTimeBetweenEvictionRunsMillis() { return this.timeBetweenEvictionRunsMillis; } /** * Set the minimum time that an idle object can sit in the pool before * it becomes subject to eviction. Default is 1800000 (30 minutes). * <p>Note that eviction runs need to be performed to take this * setting into effect. * @see #setTimeBetweenEvictionRunsMillis * @see GenericObjectPool#setMinEvictableIdleTimeMillis */ public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) { this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; } /** * Return the minimum time that an idle object can sit in the pool. */ public long getMinEvictableIdleTimeMillis() { return this.minEvictableIdleTimeMillis; } /** * Set whether the call should bock when the pool is exhausted. */ public void setBlockWhenExhausted(boolean blockWhenExhausted) { this.blockWhenExhausted = blockWhenExhausted; } /** * Specify if the call should block when the pool is exhausted. */ public boolean isBlockWhenExhausted() { return this.blockWhenExhausted; } /** * Creates and holds an ObjectPool instance. * @see #createObjectPool() */ @Override protected final void createPool() { logger.debug("Creating Commons object pool"); this.pool = createObjectPool(); } /** * Subclasses can override this if they want to return a specific Commons pool. * They should apply any configuration properties to the pool here. * <p>Default is a GenericObjectPool instance with the given pool size. * @return an empty Commons {@code ObjectPool}. * @see GenericObjectPool * @see #setMaxSize */ protected ObjectPool createObjectPool() { GenericObjectPoolConfig config = new GenericObjectPoolConfig(); config.setMaxTotal(getMaxSize()); config.setMaxIdle(getMaxIdle()); config.setMinIdle(getMinIdle()); config.setMaxWaitMillis(getMaxWait()); config.setTimeBetweenEvictionRunsMillis(getTimeBetweenEvictionRunsMillis()); config.setMinEvictableIdleTimeMillis(getMinEvictableIdleTimeMillis()); config.setBlockWhenExhausted(isBlockWhenExhausted()); return new GenericObjectPool(this, config); } /** * Borrows an object from the {@code ObjectPool}. */ @Override public Object getTarget() throws Exception { return this.pool.borrowObject(); } /** * Returns the specified object to the underlying {@code ObjectPool}. */ @Override public void releaseTarget(Object target) throws Exception { this.pool.returnObject(target); } @Override public int getActiveCount() throws UnsupportedOperationException { return this.pool.getNumActive(); } @Override public int getIdleCount() throws UnsupportedOperationException { return this.pool.getNumIdle(); } /** * Closes the underlying {@code ObjectPool} when destroying this object. */ @Override public void destroy() throws Exception { logger.debug("Closing Commons ObjectPool"); this.pool.close(); } //---------------------------------------------------------------------------- // Implementation of org.apache.commons.pool2.PooledObjectFactory interface //---------------------------------------------------------------------------- @Override public PooledObject<Object> makeObject() throws Exception { return new DefaultPooledObject<>(newPrototypeInstance()); } @Override public void destroyObject(PooledObject<Object> p) throws Exception { destroyPrototypeInstance(p.getObject()); } @Override public boolean validateObject(PooledObject<Object> p) { return true; } @Override public void activateObject(PooledObject<Object> p) throws Exception { } @Override public void passivateObject(PooledObject<Object> p) throws Exception { } }