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}