Search code examples
javaspring-aoppool

how to use aop in common-pool


I'm new to apache common pool.I use pool.borrowObject(); to get a instance from pool and do pool.returnObject(obj); in the finally block.So I want to use aop instand of writing a finally block to return instane back to pool.I think spring aop can do this,but how to get the instance "obj" in the aop:after

public class ServiceImpl implements Service{

    private GenericObjectPool<Foo> pool;

    @Override
    public void insert() {
        try {
            Foo obj = pool.borrowObject();
            //do something
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            pool.returnObject(obj);
        }
    }

    public GenericObjectPool getPool() {
        return pool;
    }

    public void setPool(GenericObjectPool pool) {
        this.pool = pool;
    }
}

Solution

  • Just if you need access to object inside aspect

    if ServiceImpl has prototype scope, you can do this

    public class ServiceImpl implements Service{
    
    private Foo obj;
    
    @Override
    public void insert() {
        . .....
            obj = pool.borrowObject();
        . .....
        return obj;
    }
    
    public Foo getFooObj(){
       return obj;
    }
    

    }

    If ServiceImpl has singleton scope , you can do this

    public class ServiceImpl implements Service{
    private ThreadLocal serviceThreadLocal = new ThreadLocal();
    
    @Override
    public void insert() {
        . .....
            obj = pool.borrowObject();
            serviceThreadLocal.set(obj);
        . .....
        return obj;
    }
    
    public Foo getFooObj(){
       return serviceThreadLocal .get();
    }
    }
    

    here you have access to the object from poll.


    or you setup / wrap handling poll logic inside an aspect

    add a custom annotation :

    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ApplyObjectFromPool {
    }
    

    and change a bit implementation :

    @Component
    public class ServiceImpl implements Service , HasObjectFromPool<Foo> {
    
        private Foo obj;
    
        @Override
        @ApplyObjectFromPool
        public void insert() {
            try {
                obj = getObjectFromPool();
                //do something
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public Foo getObjectFromPool(){
            return obj;
        }
    
        @Override
        public void setObjectFromPool(Foo object) {
            this.obj=object;
        }
    }
    

    and configure pointcut :

    @Aspect
    @Component
    public class ObjectFromPoolAspect {
        private GenericObjectPool pool = new GenericObjectPool();
    
        @Around("within(org........HasObjectFromPool+) && @annotation(applyObjectFromPool))")
        public Object applyObjectFromPool(ProceedingJoinPoint point ,
                      ApplyObjectFromPool applyObjectFromPool) throws Throwable {
            Object result;
            HasObjectFromPool target = (HasObjectFromPool) point.getTarget();
            Object objectFromPool = pool.borrowObject();
            try {
                target.setObjectFromPool(objectFromPool);
                result = point.proceed();
            }finally {
                pool.returnObject(objectFromPool);
            }
            return result;
        }
    }
    

    IMHO: if you use the pool only ServiceImpl leave it as is, if you have same logic in couple different places this about small refactoring and use Template Method Pattern or Command Pattern. In your case use aop it's the bad approach. You should change your code for making it available for aspect and not for improvement.