001/*
002 * Copyright 2002-2015 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.aop.target;
018
019import org.apache.commons.pool2.ObjectPool;
020import org.apache.commons.pool2.PooledObject;
021import org.apache.commons.pool2.PooledObjectFactory;
022import org.apache.commons.pool2.impl.DefaultPooledObject;
023import org.apache.commons.pool2.impl.GenericObjectPool;
024import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
025
026/**
027 * {@link org.springframework.aop.TargetSource} implementation that holds
028 * objects in a configurable Apache Commons2 Pool.
029 *
030 * <p>By default, an instance of {@code GenericObjectPool} is created.
031 * Subclasses may change the type of {@code ObjectPool} used by
032 * overriding the {@code createObjectPool()} method.
033 *
034 * <p>Provides many configuration properties mirroring those of the Commons Pool
035 * {@code GenericObjectPool} class; these properties are passed to the
036 * {@code GenericObjectPool} during construction. If creating a subclass of this
037 * class to change the {@code ObjectPool} implementation type, pass in the values
038 * of configuration properties that are relevant to your chosen implementation.
039 *
040 * <p>The {@code testOnBorrow}, {@code testOnReturn} and {@code testWhileIdle}
041 * properties are explicitly not mirrored because the implementation of
042 * {@code PoolableObjectFactory} used by this class does not implement
043 * meaningful validation. All exposed Commons Pool properties use the
044 * corresponding Commons Pool defaults.
045 *
046 * <p>Compatible with Apache Commons Pool 2.4, as of Spring 4.2.
047 *
048 * @author Rod Johnson
049 * @author Rob Harrop
050 * @author Juergen Hoeller
051 * @author Stephane Nicoll
052 * @author Kazuki Shimizu
053 * @since 4.2
054 * @see GenericObjectPool
055 * @see #createObjectPool()
056 * @see #setMaxSize
057 * @see #setMaxIdle
058 * @see #setMinIdle
059 * @see #setMaxWait
060 * @see #setTimeBetweenEvictionRunsMillis
061 * @see #setMinEvictableIdleTimeMillis
062 */
063@SuppressWarnings({"rawtypes", "unchecked", "serial"})
064public class CommonsPool2TargetSource extends AbstractPoolingTargetSource implements PooledObjectFactory<Object> {
065
066        private int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE;
067
068        private int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE;
069
070        private long maxWait = GenericObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS;
071
072        private long timeBetweenEvictionRunsMillis = GenericObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
073
074        private long minEvictableIdleTimeMillis = GenericObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
075
076        private boolean blockWhenExhausted = GenericObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED;
077
078        /**
079         * The Apache Commons {@code ObjectPool} used to pool target objects
080         */
081        private ObjectPool pool;
082
083
084        /**
085         * Create a CommonsPoolTargetSource with default settings.
086         * Default maximum size of the pool is 8.
087         * @see #setMaxSize
088         * @see GenericObjectPoolConfig#setMaxTotal
089         */
090        public CommonsPool2TargetSource() {
091                setMaxSize(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL);
092        }
093
094
095        /**
096         * Set the maximum number of idle objects in the pool.
097         * Default is 8.
098         * @see GenericObjectPool#setMaxIdle
099         */
100        public void setMaxIdle(int maxIdle) {
101                this.maxIdle = maxIdle;
102        }
103
104        /**
105         * Return the maximum number of idle objects in the pool.
106         */
107        public int getMaxIdle() {
108                return this.maxIdle;
109        }
110
111        /**
112         * Set the minimum number of idle objects in the pool.
113         * Default is 0.
114         * @see GenericObjectPool#setMinIdle
115         */
116        public void setMinIdle(int minIdle) {
117                this.minIdle = minIdle;
118        }
119
120        /**
121         * Return the minimum number of idle objects in the pool.
122         */
123        public int getMinIdle() {
124                return this.minIdle;
125        }
126
127        /**
128         * Set the maximum waiting time for fetching an object from the pool.
129         * Default is -1, waiting forever.
130         * @see GenericObjectPool#setMaxWaitMillis
131         */
132        public void setMaxWait(long maxWait) {
133                this.maxWait = maxWait;
134        }
135
136        /**
137         * Return the maximum waiting time for fetching an object from the pool.
138         */
139        public long getMaxWait() {
140                return this.maxWait;
141        }
142
143        /**
144         * Set the time between eviction runs that check idle objects whether
145         * they have been idle for too long or have become invalid.
146         * Default is -1, not performing any eviction.
147         * @see GenericObjectPool#setTimeBetweenEvictionRunsMillis
148         */
149        public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
150                this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
151        }
152
153        /**
154         * Return the time between eviction runs that check idle objects.
155         */
156        public long getTimeBetweenEvictionRunsMillis() {
157                return this.timeBetweenEvictionRunsMillis;
158        }
159
160        /**
161         * Set the minimum time that an idle object can sit in the pool before
162         * it becomes subject to eviction. Default is 1800000 (30 minutes).
163         * <p>Note that eviction runs need to be performed to take this
164         * setting into effect.
165         * @see #setTimeBetweenEvictionRunsMillis
166         * @see GenericObjectPool#setMinEvictableIdleTimeMillis
167         */
168        public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
169                this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
170        }
171
172        /**
173         * Return the minimum time that an idle object can sit in the pool.
174         */
175        public long getMinEvictableIdleTimeMillis() {
176                return this.minEvictableIdleTimeMillis;
177        }
178
179        /**
180         * Set whether the call should bock when the pool is exhausted.
181         */
182        public void setBlockWhenExhausted(boolean blockWhenExhausted) {
183                this.blockWhenExhausted = blockWhenExhausted;
184        }
185
186        /**
187         * Specify if the call should block when the pool is exhausted.
188         */
189        public boolean isBlockWhenExhausted() {
190                return this.blockWhenExhausted;
191        }
192
193
194        /**
195         * Creates and holds an ObjectPool instance.
196         * @see #createObjectPool()
197         */
198        @Override
199        protected final void createPool() {
200                logger.debug("Creating Commons object pool");
201                this.pool = createObjectPool();
202        }
203
204        /**
205         * Subclasses can override this if they want to return a specific Commons pool.
206         * They should apply any configuration properties to the pool here.
207         * <p>Default is a GenericObjectPool instance with the given pool size.
208         * @return an empty Commons {@code ObjectPool}.
209         * @see GenericObjectPool
210         * @see #setMaxSize
211         */
212        protected ObjectPool createObjectPool() {
213                GenericObjectPoolConfig config = new GenericObjectPoolConfig();
214                config.setMaxTotal(getMaxSize());
215                config.setMaxIdle(getMaxIdle());
216                config.setMinIdle(getMinIdle());
217                config.setMaxWaitMillis(getMaxWait());
218                config.setTimeBetweenEvictionRunsMillis(getTimeBetweenEvictionRunsMillis());
219                config.setMinEvictableIdleTimeMillis(getMinEvictableIdleTimeMillis());
220                config.setBlockWhenExhausted(isBlockWhenExhausted());
221                return new GenericObjectPool(this, config);
222        }
223
224
225        /**
226         * Borrows an object from the {@code ObjectPool}.
227         */
228        @Override
229        public Object getTarget() throws Exception {
230                return this.pool.borrowObject();
231        }
232
233        /**
234         * Returns the specified object to the underlying {@code ObjectPool}.
235         */
236        @Override
237        public void releaseTarget(Object target) throws Exception {
238                this.pool.returnObject(target);
239        }
240
241        @Override
242        public int getActiveCount() throws UnsupportedOperationException {
243                return this.pool.getNumActive();
244        }
245
246        @Override
247        public int getIdleCount() throws UnsupportedOperationException {
248                return this.pool.getNumIdle();
249        }
250
251
252        /**
253         * Closes the underlying {@code ObjectPool} when destroying this object.
254         */
255        @Override
256        public void destroy() throws Exception {
257                logger.debug("Closing Commons ObjectPool");
258                this.pool.close();
259        }
260
261
262        //----------------------------------------------------------------------------
263        // Implementation of org.apache.commons.pool2.PooledObjectFactory interface
264        //----------------------------------------------------------------------------
265
266        @Override
267        public PooledObject<Object> makeObject() throws Exception {
268                return new DefaultPooledObject<Object>(newPrototypeInstance());
269        }
270
271        @Override
272        public void destroyObject(PooledObject<Object> p) throws Exception {
273                destroyPrototypeInstance(p.getObject());
274        }
275
276        @Override
277        public boolean validateObject(PooledObject<Object> p) {
278                return true;
279        }
280
281        @Override
282        public void activateObject(PooledObject<Object> p) throws Exception {
283        }
284
285        @Override
286        public void passivateObject(PooledObject<Object> p) throws Exception {
287        }
288
289}