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
This commit is contained in:
Stephane Nicoll
2014-12-18 14:27:18 +01:00
parent 1aec6a6cc2
commit aabf73dea4
13 changed files with 437 additions and 35 deletions

View File

@@ -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;
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 {
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());

View File

@@ -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 @@
<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 @@
<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"/>

View File

@@ -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;
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.*;
* @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 {
@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 {
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 {
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 {
@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 {
// 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());
}
private void prepareTargetSource(CommonsPoolTargetSource targetSource) {
@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(CommonsPool2TargetSource targetSource) {
String beanName = "target";
StaticApplicationContext applicationContext = new StaticApplicationContext();