Создание объектов в GenericObjectPool

я провожу исследование на GenericObjectPool положить Cipher в пуле, поэтому его можно использовать повторно.

GenericObjectPool<Cipher> pool;

CipherFactory factory = new CipherFactory(); 
this.pool = new GenericObjectPool<Cipher>(factory);
pool.setMaxTotal(10);
pool.setBlockWhenExhausted(true);
pool.setMaxWaitMillis(30 * 1000);

CipherFactory

public class CipherFactory extends BasePooledObjectFactory<Cipher> {

    private boolean running = false;

    @Override
    public Cipher create() throws Exception {
        return Cipher.getInstance("DESede/CBC/NoPadding");
    }

    @Override
    public PooledObject<Cipher> wrap(Cipher arg0) {
        return new DefaultPooledObject<Cipher>(arg0);
    }

    @Override
    public boolean validateObject(PooledObject<Cipher> p) {
        //Ensures that the instance is safe to be returned by the pool
        return true;
    }

    @Override
    public void destroyObject(PooledObject<Cipher> p) {
        //Destroys an instance no longer needed by the pool. 
        System.out.println("destroying");
    }

    @Override
    public void activateObject(PooledObject<Cipher> p) throws Exception { //Reinitialize an instance to be returned by the pool

        setRunning(true);
    }

    @Override
    public void passivateObject(PooledObject<Cipher> p) throws Exception {   // reset the object after the object returns to the pool

        setRunning(false);
    }

    public void setRunning(boolean running) {

        this.running = running;
    }
//    
}

вот как я реализую ObjectPool в своем пример класс

public Key a(byte[] afyte) throws Exception {

        Cipher cipher = null;
        cipher = pool.borrowObject(); //get the object from the pool
        try {
            System.out.println("****************** After borrow ****************");
            printPool();
            cipher.init(Cipher.DECRYPT_MODE, mkkey, algParamSpec);
            byte[] de = cipher.doFinal(afyte);
            SecretKey mk = new SecretKeySpec(de, "DESede");
            return mk;
        } catch (Exception e) {
            pool.invalidateObject(cipher);
            cipher = null;
        } finally {
            if (null != cipher) {
                pool.returnObject(cipher);
                System.out.println("****************** After return ****************");
                printPool();
            }
        }
        return (Key) cipher;
    }

printPool

public void printPool() {
        System.out.println("Pool for cipher with instances DESede/CBC/NoPadding");
        System.out.println("Active [" + pool.getNumActive() + "]"); //Return the number of instances currently borrowed from this pool
        System.out.println("Idle [" + pool.getNumIdle() + "]"); //The number of instances currently idle in this pool
        System.out.println("Total Created [" + pool.getCreatedCount() + "]");      
    }

Я на правильном пути ? Можно ли увеличить размер пула ?

редактировать

ответ от @http отлично работает для меня. Но если у меня есть другой метод encryptECB(Key key, byte[] b), как я должен писать ?

любая помощь будет оценили !

1 ответов


вы на правильном пути. При построении GenericObjectPool можно использовать конструктор, который принимает объект GenericObjectPoolConfig, содержащий все значения конфигурации для пула объектов. Пример ниже позволит вашему пулу вырасти до 20 соединений, прежде чем он будет исчерпан...

GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMinIdle(2);
config.setMaxIdle(5);
config.setMaxTotal(20);

GenericObjectPool<Cipher> pool;
CipherFactory factory = new CipherFactory(); 
this.pool = new GenericObjectPool<Cipher>(factory, config);

GenericeObjectPoolConfig также имеет метод setBlockWhenExhausted, чтобы указать поведение, когда пул достиг соединений maxTotal. Видеть https://commons.apache.org/proper/commons-pool/apidocs/org/apache/commons/pool2/impl/BaseObjectPoolConfig.html#setBlockWhenExhausted-boolean- для деталей.

шаблон, который я реализую при использовании общего пула, заключается в создании 2 интерфейсов, одного для вашего объединенного объекта и одного для вашей фабрики...

public interface PooledCipher extends java.io.Closeable {
    byte[] doFinal(byte[] bytes) throws Exception;
    SecretKeySpec getSecretKeySpec(byte[] bytes) throws Exception;
}

public interface CipherFactory {
    PooledCipher getCipher() throws Exception;        
    void close();
}

реализация CipherFactory...

public class CipherFactoryImpl extends BasePooledObjectFactory<PooledCipher> 
    implements CipherFactory {

    private final GenericObjectPoolConfig config;
    private final GenericObjectPool<PooledCipher> pool;
    private final String transformation;
    private final int opmode;
    private final Key key;
    private final AlgorithmParameters params;
    private final String secretKeySpecAlgorithm;

    public CipherFactoryImpl(GenericObjectPoolConfig config, String transformation, int opmode, Key key, AlgorithmParameters params, String secretKeySpecAlgorithm) {
        this.config = config;
        this.pool = new GenericObjectPool<PooledCipher>(this, config);
        this.transformation = transformation;
        this.opmode = opmode;
        this.key = key;
        this.params = params;       
        this.secretKeySpecAlgorithm = secretKeySpecAlgorithm
    }

    @Override
    public PooledCipher create() throws Exception {
        return new PooledCipherImpl(pool, transformation, opmode, key, params, secretKeySpecAlgorithm);
    }

    @Override
    public PooledCipher getCipher() throws Exception {
        return pool.borrowObject();
    }

    @Override
    public void destroyObject(PooledObject<PooledCipher> p) throws Exception {
        try {
            PooledCipherImpl cipherImpl = (PooledCipherImpl)p.getObject();
            // do whatever you need with cipherImpl to destroy it
        } finally {
            super.destroyObject(p);
        }
    }

    @Override
    public void close() {
        pool.close();
    }

    @Override
    public PooledObject<PooledCipher> wrap(PooledCipher cipher) {
        return new DefaultPooledObject<PooledCipher>(cipher);
    }
}

реализация PooledCipher...

public class PooledCipherImpl implements PooledCipher {
    private final ObjectPool<PooledCipher> pool;
    private final Cipher cipher;
    private final String secretKeySpecAlgorithm;
    private boolean destroyOnClose = false;

    public PooledCipherImpl(ObjectPool<PooledCipher> pool, String transformation, int opmode, Key key, AlgorithmParameters params, String secretKeySpecAlgorithm) {
        this.pool = pool;
        this.cipher = Cipher.getInstance(transformation);
        this.cipher.init(opmode, key, params);
        this.secretKeySpecAlgorithm = secretKeySpecAlgorithm;
    }

    @Override
    public byte[] doFinal(byte[] bytes) throws Exception {
        try {
            return cipher.doFinal(bytes);
        } catch (Exception e) {
           destroyOnClose = true;
           throw e;
        }
    }

    @Override
    public SecretKeySpec getSecretKeySpec(byte[] bytes) {
        return new SecretKeySpec(doFinal(bytes), secretKeySpecAlgorithm);
    }

    @Override
    public void close() throws IOException {
        try {
            if (destroyOnClose) {
                pool.destroyObject(this);
            } else {
                pool.returnObject(this);
            }
        } catch (Exception e) {
            throw new IOException(e);
        }
    }
}

затем вы строите свой CipherFactory вроде этого...

String transformation = "DESede/CBC/NoPadding";
String secretKeySpecAlgorithm = "DESede";
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
// set up the poolConfig here
poolConfig.setMaxTotal(20);
CipherFactory cipherFactory = new CipherFactoryImpl(poolConfig, transformation, Cipher.DECRYPT_MODE, mkkey, algParamSpec, secretKeySpecAlgorithm);

и используйте его так...

public Key unwrapKey(byte[] tmkByte) throws Exception {
    try (PooledCipher cipher = cipherFactory.getCipher()) {
        return cipher.getSecretKeySpec(tmkByte);
    }
}

также можно повторно использовать интерфейсы PooledCipher и CipherFactory для создания других реализаций, таких как JCA.