Browse Source

Add Commons Pool 2 support

Deprecated CommonsPoolTargetSource (supporting commons pool 1.5+) in
favor of CommonsPool2TargetSource with a similar contract.

Commons Pool 2.x uses object equality while Commons Pool 1.x used
identity equality. This clearly means that Commons Pool 2 behaves
differently if several instances having the same identity according to
their `Object#equals(Object)` method are managed in the same pool. To
provide a smooth upgrade, a backward-compatible pool is created by
default; use `setUseObjectEquality(boolean)` if you need the standard
Commons Pool 2.x behavior.

Issue: SPR-12532
pull/703/merge
Stephane Nicoll 11 years ago
parent
commit
aabf73dea4
  1. 2
      build.gradle
  2. 4
      spring-aop/src/main/java/org/springframework/aop/framework/AbstractSingletonProxyFactoryBean.java
  3. 11
      spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/QuickTargetSourceCreator.java
  4. 4
      spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java
  5. 4
      spring-aop/src/main/java/org/springframework/aop/target/AbstractPoolingTargetSource.java
  6. 4
      spring-aop/src/main/java/org/springframework/aop/target/AbstractPrototypeBasedTargetSource.java
  7. 345
      spring-aop/src/main/java/org/springframework/aop/target/CommonsPool2TargetSource.java
  8. 4
      spring-aop/src/main/java/org/springframework/aop/target/CommonsPoolTargetSource.java
  9. 6
      spring-context/src/test/java/org/springframework/aop/framework/autoproxy/AdvisorAutoProxyCreatorTests.java
  10. 6
      spring-context/src/test/java/org/springframework/aop/target/CommonsPool2TargetSourceTests-context.xml
  11. 63
      spring-context/src/test/java/org/springframework/aop/target/CommonsPool2TargetSourceTests.java
  12. 9
      src/asciidoc/appendix.adoc
  13. 10
      src/asciidoc/index.adoc

2
build.gradle

@ -405,6 +405,7 @@ project("spring-aop") { @@ -405,6 +405,7 @@ project("spring-aop") {
compile("aopalliance:aopalliance:1.0")
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
optional("commons-pool:commons-pool:1.6")
optional("org.apache.commons:commons-pool2:2.2")
optional("com.jamonapi:jamon:2.79")
}
}
@ -463,6 +464,7 @@ project("spring-context") { @@ -463,6 +464,7 @@ project("spring-context") {
optional("org.jruby:jruby:1.7.17")
testCompile("javax.inject:javax.inject-tck:1")
testCompile("commons-dbcp:commons-dbcp:1.4")
testCompile("org.apache.commons:commons-pool2:2.2")
testCompile("org.slf4j:slf4j-api:${slf4jVersion}")
}

4
spring-aop/src/main/java/org/springframework/aop/framework/AbstractSingletonProxyFactoryBean.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@ -66,7 +66,7 @@ public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig @@ -66,7 +66,7 @@ public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
* @see org.springframework.aop.target.SingletonTargetSource
* @see org.springframework.aop.target.LazyInitTargetSource
* @see org.springframework.aop.target.PrototypeTargetSource
* @see org.springframework.aop.target.CommonsPoolTargetSource
* @see org.springframework.aop.target.CommonsPool2TargetSource
*/
public void setTarget(Object target) {
this.target = target;

11
spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/QuickTargetSourceCreator.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@ -17,19 +17,20 @@ @@ -17,19 +17,20 @@
package org.springframework.aop.framework.autoproxy.target;
import org.springframework.aop.target.AbstractBeanFactoryBasedTargetSource;
import org.springframework.aop.target.CommonsPoolTargetSource;
import org.springframework.aop.target.CommonsPool2TargetSource;
import org.springframework.aop.target.PrototypeTargetSource;
import org.springframework.aop.target.ThreadLocalTargetSource;
/**
* Convenient TargetSourceCreator using bean name prefixes to create one of three
* well-known TargetSource types:
* <li>: CommonsPoolTargetSource
* <li>: CommonsPool2TargetSource
* <li>% ThreadLocalTargetSource
* <li>! PrototypeTargetSource
*
* @author Rod Johnson
* @see org.springframework.aop.target.CommonsPoolTargetSource
* @author Stephane Nicoll
* @see org.springframework.aop.target.CommonsPool2TargetSource
* @see org.springframework.aop.target.ThreadLocalTargetSource
* @see org.springframework.aop.target.PrototypeTargetSource
*/
@ -44,7 +45,7 @@ public class QuickTargetSourceCreator extends AbstractBeanFactoryBasedTargetSour @@ -44,7 +45,7 @@ public class QuickTargetSourceCreator extends AbstractBeanFactoryBasedTargetSour
Class<?> beanClass, String beanName) {
if (beanName.startsWith(PREFIX_COMMONS_POOL)) {
CommonsPoolTargetSource cpts = new CommonsPoolTargetSource();
CommonsPool2TargetSource cpts = new CommonsPool2TargetSource();
cpts.setMaxSize(25);
return cpts;
}

4
spring-aop/src/main/java/org/springframework/aop/target/AbstractBeanFactoryBasedTargetSource.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@ -45,7 +45,7 @@ import org.springframework.util.ObjectUtils; @@ -45,7 +45,7 @@ import org.springframework.util.ObjectUtils;
* @see LazyInitTargetSource
* @see PrototypeTargetSource
* @see ThreadLocalTargetSource
* @see CommonsPoolTargetSource
* @see CommonsPool2TargetSource
*/
public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSource, BeanFactoryAware, Serializable {

4
spring-aop/src/main/java/org/springframework/aop/target/AbstractPoolingTargetSource.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@ -28,7 +28,7 @@ import org.springframework.beans.factory.DisposableBean; @@ -28,7 +28,7 @@ import org.springframework.beans.factory.DisposableBean;
* implementations which maintain a pool of target instances, acquiring and
* releasing a target object from the pool for each method invocation.
* This abstract base class is independent of concrete pooling technology;
* see the subclass {@link CommonsPoolTargetSource} for a concrete example.
* see the subclass {@link CommonsPool2TargetSource} for a concrete example.
*
* <p>Subclasses must implement the {@link #getTarget} and
* {@link #releaseTarget} methods based on their chosen object pool.

4
spring-aop/src/main/java/org/springframework/aop/target/AbstractPrototypeBasedTargetSource.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@ -41,7 +41,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory; @@ -41,7 +41,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
* @see org.springframework.beans.factory.BeanFactory#getBean
* @see PrototypeTargetSource
* @see ThreadLocalTargetSource
* @see CommonsPoolTargetSource
* @see CommonsPool2TargetSource
*/
@SuppressWarnings("serial")
public abstract class AbstractPrototypeBasedTargetSource extends AbstractBeanFactoryBasedTargetSource {

345
spring-aop/src/main/java/org/springframework/aop/target/CommonsPool2TargetSource.java

@ -0,0 +1,345 @@ @@ -0,0 +1,345 @@
/*
* Copyright 2002-2015 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>Commons Pool 2.x uses object equality while Commons Pool 1.x used identity
* equality. This clearly means that Commons Pool 2 behaves differently if several
* instances having the same identity according to their {@link Object#equals(Object)}
* method are managed in the same pool. To provide a smooth upgrade, a
* backward-compatible pool is created by default; use {@link #setUseObjectEquality(boolean)}
* if you need the standard Commons Pool 2.x behavior.
*
* <p>Compatible with Apache Commons Pool 2.2
*
* @author Rod Johnson
* @author Rob Harrop
* @author Juergen Hoeller
* @author Stephane Nicoll
* @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_TOTAL;
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;
private boolean useObjectEquality;
/**
* The Jakarta 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#setMaxTotal
*/
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 blockWhenExhausted;
}
/**
* Set if the pool should use object equality. Commons Pool 1.x has no specific requirement in
* that regard and allows two distinct instances being equal to be put in the same pool. However,
* this behavior has changed with commons pool 2. To preserve backward compatibility, the pool
* is configured to use reference equality ({@code false}.
*/
public void setUseObjectEquality(boolean useObjectEquality) {
this.useObjectEquality = useObjectEquality;
}
/**
* Specify if the pool should use object equality. Return {@code false} if it should use
* reference equality (as it was the case for Commons Pool 1.x)
*/
public boolean isUseObjectEquality() {
return useObjectEquality;
}
/**
* 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);
}
/**
* Borrow an object from the {@code ObjectPool}.
*/
@Override
public Object getTarget() throws Exception {
Object o = this.pool.borrowObject();
return (isUseObjectEquality() ? o : ((IdentityWrapper)o).target);
}
/**
* Returns the specified object to the underlying {@code ObjectPool}.
*/
@Override
public void releaseTarget(Object target) throws Exception {
Object value = (isUseObjectEquality() ? target : new IdentityWrapper(target));
this.pool.returnObject(value);
}
@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 {
Object target = newPrototypeInstance();
Object poolValue = (isUseObjectEquality() ? target : new IdentityWrapper(target));
return new DefaultPooledObject<Object>(poolValue);
}
@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 {
}
/**
* Wraps the target type in the pool to restore the behavior of commons-pool 1.x.
*/
private static class IdentityWrapper {
private final Object target;
public IdentityWrapper(Object target) {
this.target = target;
}
@Override
public int hashCode() {
return System.identityHashCode(this.target);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
IdentityWrapper that = (IdentityWrapper) o;
return !(target != null ? !(target == that.target) : that.target != null);
}
}
}

4
spring-aop/src/main/java/org/springframework/aop/target/CommonsPoolTargetSource.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@ -58,8 +58,10 @@ import org.springframework.core.Constants; @@ -58,8 +58,10 @@ import org.springframework.core.Constants;
* @see #setMaxWait
* @see #setTimeBetweenEvictionRunsMillis
* @see #setMinEvictableIdleTimeMillis
* @deprecated as of Spring 4.2, in favor of {@link CommonsPool2TargetSource}
*/
@SuppressWarnings({"rawtypes", "unchecked", "serial"})
@Deprecated
public class CommonsPoolTargetSource extends AbstractPoolingTargetSource implements PoolableObjectFactory {
private static final Constants constants = new Constants(GenericObjectPool.class);

6
spring-context/src/test/java/org/springframework/aop/framework/autoproxy/AdvisorAutoProxyCreatorTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@ -25,7 +25,7 @@ import org.springframework.aop.framework.Advised; @@ -25,7 +25,7 @@ import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.autoproxy.target.AbstractBeanFactoryBasedTargetSourceCreator;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.target.AbstractBeanFactoryBasedTargetSource;
import org.springframework.aop.target.CommonsPoolTargetSource;
import org.springframework.aop.target.CommonsPool2TargetSource;
import org.springframework.aop.target.LazyInitTargetSource;
import org.springframework.aop.target.PrototypeTargetSource;
import org.springframework.aop.target.ThreadLocalTargetSource;
@ -154,7 +154,7 @@ public final class AdvisorAutoProxyCreatorTests { @@ -154,7 +154,7 @@ public final class AdvisorAutoProxyCreatorTests {
test = (ITestBean) bf.getBean(":test");
assertTrue(AopUtils.isAopProxy(test));
Advised advised = (Advised) test;
assertTrue(advised.getTargetSource() instanceof CommonsPoolTargetSource);
assertTrue(advised.getTargetSource() instanceof CommonsPool2TargetSource);
assertEquals("Rod", test.getName());
// Check that references survived pooling
assertEquals("Kerry", test.getSpouse().getName());

6
spring-context/src/test/java/org/springframework/aop/target/CommonsPoolTargetSourceTests-context.xml → spring-context/src/test/java/org/springframework/aop/target/CommonsPool2TargetSourceTests-context.xml

@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
<property name="count"><value>10</value></property>
</bean>
<bean id="poolTargetSource" class="org.springframework.aop.target.CommonsPoolTargetSource">
<bean id="poolTargetSource" class="org.springframework.aop.target.CommonsPool2TargetSource">
<property name="targetBeanName"><value>prototypeTest</value></property>
<property name="maxSize"><value>25</value></property>
</bean>
@ -44,7 +44,7 @@ @@ -44,7 +44,7 @@
<bean id="prototypePerson" class="org.springframework.tests.sample.beans.SerializablePerson" scope="prototype"/>
<bean id="personPoolTargetSource" class="org.springframework.aop.target.CommonsPoolTargetSource">
<bean id="personPoolTargetSource" class="org.springframework.aop.target.CommonsPool2TargetSource">
<property name="targetBeanName"><value>prototypePerson</value></property>
<property name="maxSize"><value>10</value></property>
</bean>
@ -57,7 +57,7 @@ @@ -57,7 +57,7 @@
<bean id="maxSizePooledPerson" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetSource">
<bean class="org.springframework.aop.target.CommonsPoolTargetSource">
<bean class="org.springframework.aop.target.CommonsPool2TargetSource">
<property name="targetBeanName" value="prototypePerson"/>
<property name="maxSize" value="10"/>
<property name="maxWait" value="1"/>

63
spring-context/src/test/java/org/springframework/aop/target/CommonsPoolTargetSourceTests.java → spring-context/src/test/java/org/springframework/aop/target/CommonsPool2TargetSourceTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@ -18,10 +18,11 @@ package org.springframework.aop.target; @@ -18,10 +18,11 @@ package org.springframework.aop.target;
import java.util.NoSuchElementException;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.aop.framework.Advised;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
@ -43,8 +44,12 @@ import static org.junit.Assert.*; @@ -43,8 +44,12 @@ import static org.junit.Assert.*;
* @author Rod Johnson
* @author Rob Harrop
* @author Chris Beams
* @author Stephane Nicoll
*/
public class CommonsPoolTargetSourceTests {
public class CommonsPool2TargetSourceTests {
@Rule
public final ExpectedException thrown = ExpectedException.none();
/**
* Initial count value set in bean factory XML
@ -109,7 +114,7 @@ public class CommonsPoolTargetSourceTests { @@ -109,7 +114,7 @@ public class CommonsPoolTargetSourceTests {
@Test
public void testTargetSourceSerializableWithoutConfigMixin() throws Exception {
CommonsPoolTargetSource cpts = (CommonsPoolTargetSource) beanFactory.getBean("personPoolTargetSource");
CommonsPool2TargetSource cpts = (CommonsPool2TargetSource) beanFactory.getBean("personPoolTargetSource");
SingletonTargetSource serialized = (SingletonTargetSource) SerializationTestUtils.serializeAndDeserialize(cpts);
assertTrue(serialized.getTarget() instanceof Person);
@ -121,7 +126,7 @@ public class CommonsPoolTargetSourceTests { @@ -121,7 +126,7 @@ public class CommonsPoolTargetSourceTests {
Person pooled = (Person) beanFactory.getBean("pooledPerson");
//System.out.println(((Advised) pooled).toProxyConfigString());
assertTrue(((Advised) pooled).getTargetSource() instanceof CommonsPoolTargetSource);
assertTrue(((Advised) pooled).getTargetSource() instanceof CommonsPool2TargetSource);
//((Advised) pooled).setTargetSource(new SingletonTargetSource(new SerializablePerson()));
Person serialized = (Person) SerializationTestUtils.serializeAndDeserialize(pooled);
@ -134,7 +139,7 @@ public class CommonsPoolTargetSourceTests { @@ -134,7 +139,7 @@ public class CommonsPoolTargetSourceTests {
public void testHitMaxSize() throws Exception {
int maxSize = 10;
CommonsPoolTargetSource targetSource = new CommonsPoolTargetSource();
CommonsPool2TargetSource targetSource = new CommonsPool2TargetSource();
targetSource.setMaxSize(maxSize);
targetSource.setMaxWait(1);
prepareTargetSource(targetSource);
@ -169,7 +174,7 @@ public class CommonsPoolTargetSourceTests { @@ -169,7 +174,7 @@ public class CommonsPoolTargetSourceTests {
@Test
public void testHitMaxSizeLoadedFromContext() throws Exception {
Advised person = (Advised) beanFactory.getBean("maxSizePooledPerson");
CommonsPoolTargetSource targetSource = (CommonsPoolTargetSource) person.getTargetSource();
CommonsPool2TargetSource targetSource = (CommonsPool2TargetSource) person.getTargetSource();
int maxSize = targetSource.getMaxSize();
Object[] pooledInstances = new Object[maxSize];
@ -195,18 +200,54 @@ public class CommonsPoolTargetSourceTests { @@ -195,18 +200,54 @@ public class CommonsPoolTargetSourceTests {
// release all objects
for (int i = 0; i < pooledInstances.length; i++) {
System.out.println(i);
targetSource.releaseTarget(pooledInstances[i]);
}
}
@Test
public void testSetWhenExhaustedAction() {
CommonsPoolTargetSource targetSource = new CommonsPoolTargetSource();
targetSource.setWhenExhaustedActionName("WHEN_EXHAUSTED_BLOCK");
assertEquals(GenericObjectPool.WHEN_EXHAUSTED_BLOCK, targetSource.getWhenExhaustedAction());
CommonsPool2TargetSource targetSource = new CommonsPool2TargetSource();
targetSource.setBlockWhenExhausted(true);
assertEquals(true, targetSource.isBlockWhenExhausted());
}
@Test
public void referenceIdentityByDefault() throws Exception {
CommonsPool2TargetSource targetSource = new CommonsPool2TargetSource();
targetSource.setMaxWait(1);
prepareTargetSource(targetSource);
Object first = targetSource.getTarget();
Object second = targetSource.getTarget();
assertTrue(first instanceof SerializablePerson);
assertTrue(second instanceof SerializablePerson);
assertEquals(first, second);
targetSource.releaseTarget(first);
targetSource.releaseTarget(second);
}
@Test
public void objectIdentityReleaseWithSeveralEqualInstances() throws Exception{
CommonsPool2TargetSource targetSource = new CommonsPool2TargetSource();
targetSource.setUseObjectEquality(true);
targetSource.setMaxWait(1);
prepareTargetSource(targetSource);
Object first = targetSource.getTarget();
Object second = targetSource.getTarget();
assertTrue(first instanceof SerializablePerson);
assertTrue(second instanceof SerializablePerson);
assertEquals(first, second);
targetSource.releaseTarget(first);
thrown.expect(IllegalStateException.class); // Only one object in pool
targetSource.releaseTarget(second);
}
private void prepareTargetSource(CommonsPoolTargetSource targetSource) {
private void prepareTargetSource(CommonsPool2TargetSource targetSource) {
String beanName = "target";
StaticApplicationContext applicationContext = new StaticApplicationContext();

9
src/asciidoc/appendix.adoc

@ -2049,12 +2049,17 @@ A crucial difference between Spring pooling and SLSB pooling is that Spring pool @@ -2049,12 +2049,17 @@ A crucial difference between Spring pooling and SLSB pooling is that Spring pool
be applied to any POJO. As with Spring in general, this service can be applied in a
non-invasive way.
Spring provides out-of-the-box support for Jakarta Commons Pool 1.3, which provides a
Spring provides out-of-the-box support for Commons Pool 2.2, which provides a
fairly efficient pooling implementation. You'll need the commons-pool Jar on your
application's classpath to use this feature. It's also possible to subclass
`org.springframework.aop.target.AbstractPoolingTargetSource` to support any other
pooling API.
[NOTE]
====
Commons Pool 1.5+ is also supported but deprecated as of Spring Framework 4.2.
====
Sample configuration is shown below:
[source,xml,indent=0]
@ -2064,7 +2069,7 @@ Sample configuration is shown below: @@ -2064,7 +2069,7 @@ Sample configuration is shown below:
... properties omitted
</bean>
<bean id="poolTargetSource" class="org.springframework.aop.target.CommonsPoolTargetSource">
<bean id="poolTargetSource" class="org.springframework.aop.target.CommonsPool2TargetSource">
<property name="targetBeanName" value="businessObjectTarget"/>
<property name="maxSize" value="25"/>
</bean>

10
src/asciidoc/index.adoc

@ -18305,12 +18305,18 @@ A crucial difference between Spring pooling and SLSB pooling is that Spring pool @@ -18305,12 +18305,18 @@ A crucial difference between Spring pooling and SLSB pooling is that Spring pool
be applied to any POJO. As with Spring in general, this service can be applied in a
non-invasive way.
Spring provides out-of-the-box support for Jakarta Commons Pool 1.3, which provides a
Spring provides out-of-the-box support for Commons Pool 2.2, which provides a
fairly efficient pooling implementation. You'll need the commons-pool Jar on your
application's classpath to use this feature. It's also possible to subclass
`org.springframework.aop.target.AbstractPoolingTargetSource` to support any other
pooling API.
[NOTE]
====
Commons Pool 1.5+ is also supported but deprecated as of Spring Framework 4.2.
====
Sample configuration is shown below:
[source,xml,indent=0]
@ -18321,7 +18327,7 @@ Sample configuration is shown below: @@ -18321,7 +18327,7 @@ Sample configuration is shown below:
... properties omitted
</bean>
<bean id="poolTargetSource" class="org.springframework.aop.target.CommonsPoolTargetSource">
<bean id="poolTargetSource" class="org.springframework.aop.target.CommonsPool2TargetSource">
<property name="targetBeanName" value="businessObjectTarget"/>
<property name="maxSize" value="25"/>
</bean>

Loading…
Cancel
Save