Recipe22.3.Applying Resource Pooling


Recipe 22.3. Applying Resource Pooling

Problem

You want to optimize the access to a commonly used resource by creating a reusable pool of those resources without affecting the existing operation of your application.

Solution

Using the Director aspect-oriented design pattern, create an abstract aspect that defines the roles of the Resource and Resource Pool as interfaces and the generic reusable behavior of resource pooling, as shown in Example 22-6. The abstract resource pooling aspect can then be specialized for each resource to be pooled within your target application.

Example 22-6. Defining the generic resource pooling behavior in an abstract aspect
public abstract aspect ResourcePoolingAspect  {      public interface Resource    {           }        public interface ResourcePool    {       public void add(Resource resource);       public Resource remove( );    }        protected class ResourcePoolsCollection    {       WeakHashMap pools = new WeakHashMap( );              public void putResourcePool(ResourcePool pool,        Class resourceClass)       {          pools.put(resourceClass, pool);       }              public ResourcePool getResourcePool(Class resourceClass)       {          return (ResourcePool) pools.get(resourceClass);       }    }        protected ResourcePoolsCollection resourcePools =     new ResourcePoolsCollection( );        public ResourcePoolingAspect( )    {         initializeSpecificPool( );    }        protected abstract void initializeSpecificPool( );        private pointcut excludeAspects( ) : !within(ResourcePoolingAspect+);        public abstract pointcut catchResourceConstruction( );        public abstract pointcut catchResourceDestruction(Resource resource);        Object around( ) : catchResourceConstruction( ) && excludeAspects( )    {       ResourcePool resources =           resourcePools.getResourcePool(             thisJoinPoint.getSignature( ).getDeclaringType( ));       return resources.remove( );    }        Object around(Resource resource) :        catchResourceDestruction(resource) && excludeAspects( )    {       ResourcePool resources =           resourcePools.getResourcePool(             thisJoinPoint.getSignature( ).getDeclaringType( ));       Object returnValue = resourceReturnedToPool(resource);       System.out.println("Resource added back into pool: " + resource);       resources.add(resource);       return returnValue;    }        protected abstract Object resourceReturnedToPool(Resource resource);        // A resource must use and resort to a simple default constructor     // for initialization    // As protected by the warning declared below    declare warning : call(public Resource+.new(*,..))     : "Use a default constructor when using classes declared as        pooled resources"; }

Discussion

Example 22-6 shows how a reusable abstract aspect can be defined that will provide resource pooling within an application that originally did not support it. The Resource and ResourcePool interfaces are declared so the generic resource pooling behavior can be defined against those interfaces separately from how those interfaces may be implemented.

The behavior declared within the abstract ResourcePoolingAspect is shared across all of the resource pools declared as subaspects. The ResourcePoolCollection class provides a common repository for all the resource pools throughout your application so the generic code can look up a specific resource pool based on the class of the resource it contains.

When the ResourcePoolingAspect is initialized, a call is made to the abstract initializeSpecificPool( ) method. This method is implemented by subaspects of the ResourcePoolingAspect to initialize their own pool implementations and add them to the ResourcePoolCollection.

The abstract catchResourceConstruction() and catchResourceDestruction(Resource) pointcuts are provided so subaspects can specify the join points where a resource is first accessed and released. The pointcuts are then applied to the two sets of around( ) advice that override when a resource is created or destroyed so the resources that exist in the corresponding resource pool can be used instead. The abstract resourceReturnedToPool() method is called when a resource is released and placed back in its corresponding pool to give the subaspects an opportunity to do any applicable post-processing.

Example 22-7 shows how the abstract ResourcePoolingAspect can be applied to an example application. Once the aspect is applied, objects of the BusinessResource class are obtained and released back into a resource pool transparently to the rest of the application.

Example 22-7. Applying resource pooling to a resource within a simple example application
import java.util.List; import java.util.ArrayList; import com.oreilly.aspectjcookbook.BusinessResource; public aspect BusinessResourcePoolingAspect extends ResourcePoolingAspect {    declare parents : BusinessResource implements Resource;    public pointcut catchResourceConstruction( ) : call(public     BusinessResource.new( ));        public pointcut catchResourceDestruction(Resource resource) :        call(public void BusinessResource.close( )) && target(resource);    private class BusinessResourcePool implements ResourcePool    {       private static final int RESOURCE_POOL_SIZE = 10;              List resources = new ArrayList( );              public BusinessResourcePool( )       {          for (int x = 0; x < RESOURCE_POOL_SIZE; x++)          {             this.add(new BusinessResource( ));          }       }              public synchronized void add(Resource resource)       {          resources.add(resource);       }              public synchronized Resource remove( )       {          if (resources.size( ) == 0)          {             resources.add(new BusinessResource( ));          }          return (Resource) resources.remove(resources.size( ) - 1);       }    }        protected void initializeSpecificPool( )    {       try       {          this.resourcePools.putResourcePool(new BusinessResourcePool( ),                 Class.forName("com.oreilly.aspectjcookbook.BusinessResource"));       }       catch (ClassNotFoundException cnfe)       {          System.err.println("Couldn't find resource class to pool");       }    }        protected Object resourceReturnedToPool(Resource resource)    {       // Do any resource specific tudying up if necessary       // None to do in this example       return null;    } }

The BusinessResourcePoolingAspect applies the Resource role to the example application's BusinessResource class. The catchResourceConstruction() and catchRe-sourceDestruction(Resource) pointcuts are implemented to specify when a BusinessResource is constructed and when it is released by a call to its close() method.

The ResourcePool role is implemented by the BusinessResourcePool class, which contains a list of BusinessResource objects. If the application needed it, this resource pool could be implemented in more efficient ways depending on the situation and the requirements.

Finally, the initializeSpecificPool() method is implemented to construct the single instance of the BusinessResourcePool. This BusinessResourcePool will be added to the ResourcePoolCollection managed by the parent ResourcePoolingAspect. The BusinessResource objects do not require anything special to be done when they are released back into the pool so the resourceReturnedToPool(Resource) method does nothing extra in this case.

See Also

The call(Signature) pointcut is described in Recipe 4.1; using the call(Signature) pointcut to capture and override a call to a constructor is examined in Recipes Recipe 7.1 and Recipe 20.1; using the target( ) pointcut is described in Recipe 4.3; the around( ) form of advice is covered in Recipe 13.4; defining abstract aspects and pointcuts is explained in Recipe 15.4; the Director aspect-oriented design pattern is explained in Recipe 23.3.



AspectJ Cookbook
Aspectj Cookbook
ISBN: 0596006543
EAN: 2147483647
Year: 2006
Pages: 203
Authors: Russ Miles

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net