/*
 * Copyright 2002-2018 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
 *
 *      https://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;

import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

TargetSource implementation that holds objects in a configurable Apache Commons2 Pool.

By default, an instance of GenericObjectPool is created. Subclasses may change the type of ObjectPool used by overriding the createObjectPool() method.

Provides many configuration properties mirroring those of the Commons Pool GenericObjectPool class; these properties are passed to the GenericObjectPool during construction. If creating a subclass of this class to change the ObjectPool implementation type, pass in the values of configuration properties that are relevant to your chosen implementation.

The testOnBorrow, testOnReturn and testWhileIdle properties are explicitly not mirrored because the implementation of PoolableObjectFactory used by this class does not implement meaningful validation. All exposed Commons Pool properties use the corresponding Commons Pool defaults.

Compatible with Apache Commons Pool 2.4, as of Spring 4.2.

Author:Rod Johnson, Rob Harrop, Juergen Hoeller, Stephane Nicoll, Kazuki Shimizu
See Also:
Since:4.2
/** * {@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 ObjectPool used to pool target objects.
/** * The Apache Commons {@code ObjectPool} used to pool target objects. */
@Nullable private ObjectPool pool;
Create a CommonsPoolTargetSource with default settings. Default maximum size of the pool is 8.
See Also:
  • setMaxSize
  • setMaxTotal.setMaxTotal
/** * 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 Also:
  • setMaxIdle.setMaxIdle
/** * 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.
/** * 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 Also:
  • setMinIdle.setMinIdle
/** * 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.
/** * 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 Also:
  • setMaxWaitMillis.setMaxWaitMillis
/** * 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.
/** * 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 Also:
  • setTimeBetweenEvictionRunsMillis.setTimeBetweenEvictionRunsMillis
/** * 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.
/** * 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).

Note that eviction runs need to be performed to take this setting into effect.

See Also:
  • setTimeBetweenEvictionRunsMillis
  • setMinEvictableIdleTimeMillis.setMinEvictableIdleTimeMillis
/** * 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.
/** * 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.
/** * 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.
/** * Specify if the call should block when the pool is exhausted. */
public boolean isBlockWhenExhausted() { return this.blockWhenExhausted; }
Creates and holds an ObjectPool instance.
See Also:
  • createObjectPool()
/** * 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.

Default is a GenericObjectPool instance with the given pool size.

See Also:
Returns:an empty Commons ObjectPool.
/** * 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 ObjectPool.
/** * Borrows an object from the {@code ObjectPool}. */
@Override public Object getTarget() throws Exception { Assert.state(this.pool != null, "No Commons ObjectPool available"); return this.pool.borrowObject(); }
Returns the specified object to the underlying ObjectPool.
/** * Returns the specified object to the underlying {@code ObjectPool}. */
@Override public void releaseTarget(Object target) throws Exception { if (this.pool != null) { this.pool.returnObject(target); } } @Override public int getActiveCount() throws UnsupportedOperationException { return (this.pool != null ? this.pool.getNumActive() : 0); } @Override public int getIdleCount() throws UnsupportedOperationException { return (this.pool != null ? this.pool.getNumIdle() : 0); }
Closes the underlying ObjectPool when destroying this object.
/** * Closes the underlying {@code ObjectPool} when destroying this object. */
@Override public void destroy() throws Exception { if (this.pool != null) { 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 { } }