dynaop manual

Chapter 5. Cookbook

Be Proxy Aware

Mixins and interceptors often need a reference to their surrounding proxy. The framework will provide this reference at creation time if the mixin or interceptor implements the ProxyAware interface. One example is the subject/observer design pattern. A subject mixin should pass a proxy reference to the observers rather than a "this" reference.

Implement a Dispatching Interceptor

The world is not always perfect. Due to incosistencies in method semantics, a crosscutting concern may not lend itself to being cleanly abstracted into a single interceptor. In some situations, you want to intercept methods with a specific signature. DispatchInterceptor makes this easy. Say for example that we only want to intercept setId() methods:

Example 5.1. dispatch interceptor

public class SetIdInterceptor extends DispatchInterceptor {
 
  public void setId(long id) throws Throwable {
    proceed();
    Log.log("ID changed to " + id + ".");
  }
}

DispatchInterceptor also automatically creates our method pointcut for us, matching only public methods implemented by our interceptor class:

Example 5.2. dispatch interceptor configuration

interceptor(
  ALL_CLASSES,
  DispatchInterceptor.methodPointcut(SetIdInterceptor.class),
  new SetIdInterceptor()
);

Hook Proxy Factory Transparently

It's not necessary to explicitly call the ProxyFactory from our code every time we create an object. Doing so is an example of a crosscutting concern. We can use a method interceptor to abstract out this concern.

Example 5.3. transparent proxy factory hook

/**
 * Wraps method results using default proxy factory.
 */
public class ProxyFactoryInterceptor implements Interceptor {

  public Object intercept(Invocation invocation) throws Throwable {
    return ProxyFactory.getInstance().wrap(invocation.proceed());
  }
}

/**
 * Application factory class. Creates domain objects.
 */
public class Factory {

  public Person createPerson() {
    return new PersonImpl();
  }
	
  public Book createBook() {
    return new BookImpl();
  }
	
  static Factory instance = 
    (Factory) ProxyFactory.getInstance().extend(Factory.class);
	
  public static Factory getInstance() {
    return instance;
  }
}

Apply the ProxyFactoryInterceptor advice to the create methods on the factory and the Person and Book instance will get proxied. Now we have one explicit hook instead of three.