springboot使用commons-pool2實現對象池
一. 連接池概述
頻繁的創建和銷毀,會極大的降低系統的性能,而對象池會在初始化的時候會創建一定數量的對象,每次訪問只需從對象池中獲取對象,使用完畢后再放回對象池,並不是直接銷毀,這樣可以保證程序重復使用同一個對象而不需要每次訪問都創建和銷毀對象, 從而提高系統性能。
二. commons-pool2介紹
加入pool2依賴:
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.6.2</version> </dependency>
pool2的組成
PooledObject(池化對象) PooledObjectFactory(對象工廠) ObjectPool (對象池)
需要池化的對象
/** * 需要池化的對象 * * @author lz * @date 2019/7/30 */ public class TestObject { private String name; private boolean isActive; public TestObject() { } public TestObject(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isActive() { return isActive; } public void setActive(boolean active) { isActive = active; } public void destroy(){ } }
TestObject 工廠
在commons-pool2中有兩種工廠:PooledObjectFactory 和KeyedPooledObjectFactory,我們使用前者。
public interface PooledObjectFactory<T> { //創建對象 PooledObject<T> makeObject(); //激活對象 void activateObject(PooledObject<T> obj); //鈍化對象 void passivateObject(PooledObject<T> obj); //驗證對象 boolean validateObject(PooledObject<T> obj); //銷毀對象 void destroyObject(PooledObject<T> obj); }
創建TestObjectFactory只需要繼承BasePooledObjectFactory這個抽象類 ,而它則實現了PooledObjectFactory,也可以直接實現PooledObjectFactory接口;我們使用實現PooledObjectFactory接口:
import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.PooledObjectFactory; import org.apache.commons.pool2.impl.DefaultPooledObject; /** * TestObject 工廠類 * * @author lz * @date 2019/7/30 */ public class TestObjectFactory implements PooledObjectFactory<TestObject> { /** * /構造一個封裝對象 * * @return * @throws Exception */ @Override public PooledObject<TestObject> makeObject() throws Exception { return new DefaultPooledObject<>(new TestObject()); } /** * 銷毀對象 * * @param p * @throws Exception */ @Override public void destroyObject(PooledObject<TestObject> p) throws Exception { p.getObject().destroy(); } /** * 驗證對象是否可用 * * @param p * @return */ @Override public boolean validateObject(PooledObject<TestObject> p) { return p.getObject().isActive(); } /** * 激活一個對象,使其可用用 * * @param p * @throws Exception */ @Override public void activateObject(PooledObject<TestObject> p) throws Exception { p.getObject().setActive(true); } /** * 鈍化一個對象,也可以理解為反初始化 * * @param p * @throws Exception */ @Override public void passivateObject(PooledObject<TestObject> p) throws Exception { } }
創建一個對象池
import org.apache.commons.pool2.PooledObjectFactory; import org.apache.commons.pool2.impl.AbandonedConfig; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; /** * 自定義對象池 * * @author lz * @date 2019/7/30 */ public class TestObjectPool extends GenericObjectPool<TestObject> { public TestObjectPool(PooledObjectFactory<TestObject> factory) { super(factory); } public TestObjectPool(PooledObjectFactory<TestObject> factory, GenericObjectPoolConfig<TestObject> config) { super(factory, config); } public TestObjectPool(PooledObjectFactory<TestObject> factory, GenericObjectPoolConfig<TestObject> config, AbandonedConfig abandonedConfig) { super(factory, config, abandonedConfig); } }
spring 部分
創建對象池配置類
import org.springframework.boot.context.properties.ConfigurationProperties; /** * 對象池配置 * * @author lz * @date 2019/7/30 */ @ConfigurationProperties(prefix = PoolProperties.PROJECT_PREFIX) public class PoolProperties { public static final String PROJECT_PREFIX = "project.object"; /** * 最大空閑 */ private int maxIdle = 5; /** * 最大總數 */ private int maxTotal = 20; /** * 最小空閑 */ private int minIdle = 2; /** * 初始化連接數 */ private int initialSize = 3; public int getMaxIdle() { return maxIdle; } public void setMaxIdle(int maxIdle) { this.maxIdle = maxIdle; } public int getMaxTotal() { return maxTotal; } public void setMaxTotal(int maxTotal) { this.maxTotal = maxTotal; } public int getMinIdle() { return minIdle; } public void setMinIdle(int minIdle) { this.minIdle = minIdle; } public int getInitialSize() { return initialSize; } public void setInitialSize(int initialSize) { this.initialSize = initialSize; } }
創建自動配置類
import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.annotation.PreDestroy; /** * 對象池自動裝配 * * @author lz * @date 2019/7/30 */ @EnableConfigurationProperties(PoolProperties.class) @Configuration public class PoolAutoConfiguration { private final PoolProperties poolProperties; private TestObjectPool pool; @Autowired public PoolAutoConfiguration(PoolProperties poolProperties) { this.poolProperties = poolProperties; } @ConditionalOnClass({TestObjectFactory.class}) @Bean protected TestObjectPool faceSDKPool() { TestObjectFactory faceSDKFactory = new TestObjectFactory(); //設置對象池的相關參數 GenericObjectPoolConfig<TestObject> poolConfig = new GenericObjectPoolConfig<>(); poolConfig.setMaxIdle(poolProperties.getMaxIdle()); poolConfig.setMaxTotal(poolProperties.getMaxTotal()); poolConfig.setMinIdle(poolProperties.getMinIdle()); poolConfig.setBlockWhenExhausted(true); poolConfig.setTestOnBorrow(true); poolConfig.setTestOnReturn(true); poolConfig.setTestWhileIdle(true); poolConfig.setTimeBetweenEvictionRunsMillis(1000 * 60 * 30); //一定要關閉jmx,不然springboot啟動會報已經注冊了某個jmx的錯誤 poolConfig.setJmxEnabled(false); //新建一個對象池,傳入對象工廠和配置 pool = new TestObjectPool(faceSDKFactory, poolConfig); initPool(poolProperties.getInitialSize(), poolProperties.getMaxIdle()); return pool; } /** * 預先加載testObject對象到對象池中 * * @param initialSize 初始化連接數 * @param maxIdle 最大空閑連接數 */ private void initPool(int initialSize, int maxIdle) { if (initialSize <= 0) { return; } int size = Math.min(initialSize, maxIdle); 