Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES

## Package org.nanocontainer.aop

Lets you configure aspects on components in a `PicoContainer`.

See:
Description

Interface Summary
AspectablePicoContainer | A `org.picocontainer.MutablePicoContainer` that supports the application of aspects to components in the container.
AspectablePicoContainerFactory | Produces `AspectablePicoContainer` objects.
AspectsApplicator | Applies aspects to a component.
AspectsContainer | Represents the collection of aspects (pointuts + advice) to be applied to a Pico container.
AspectsManager | Object that can both register aspects and apply them to components.
ClassPointcut | Pointcut that picks classes.
ComponentPointcut | Pointcut that picks component keys.
MethodPointcut | Pointcut that picks methods.
PointcutsFactory | Produces pointcuts.

Exception Summary
MalformedRegularExpressionException | Exception thrown by `PointcutsFactory` when it is passed an invalid regular expression.

## Package org.nanocontainer.aop Description

Lets you configure aspects on components in a `PicoContainer`. Two kinds of advice are supported, interceptors and mixins. An interceptor is invoked around method calls. Interceptors implement the `org.aopalliance.interceptor.MethodInterceptor` interface. Mixins allow you to add new methods and behavior to an existing object. You can think of them as a way of dynamically providing multiple inheritance in java. Mixins can be any kind of object; they are not required to extend or implement anything. You can configure aspects in Java, or using groovy. Advice can be configured for all components in a container, using pointcuts, or advice can be applied to just one component. Advice objects may themselves have dependencies on other components, supplied by the container. Currently, dynaop is used to apply the aspects. Other backends may be supported in the future.

## Configuring Aspects

For the following examples, we'll use the following logging interceptor:

        public class LoggingInterceptor implements org.aopalliance.intercept.MethodInterceptor {
            public Object invoke(MethodInvocation invocation) throws Throwable {
                System.out.println("start");
                Object result = invocation.proceed();
                System.out.println("end");
                return result;
            }
        }

We'll also assume that we have a `Dao` interface, with an implementation class `DaoImpl`.

### Java Configuration

The primary interface for configuring aspects in Java is `AspectablePicoContainer`. To create one you need a `AspectablePicoContainerFactory`. The following example applies our logging interceptor to all methods of all instances of `Dao` in the container:

        AspectablePicoContainerFactory containerFactory = new DynaopAspectablePicoContainerFactory();
        AspectablePicoContainer pico = containerFactory.createContainer();
        PointcutsFactory cuts = pico.getPointcutsFactory();

        LoggingInterceptor logger = new LoggingInterceptor();
        pico.registerComponentImplementation(Dao.class, DaoImpl.class);
        pico.registerInterceptor(cuts.instancesOf(Dao.class), cuts.allMethods(), logger);

        Dao dao = (Dao) pico.getComponentInstance(Dao.class);
        dao.aMethod(); // will print 'startend'

If we wanted to apply our interceptor to just one component, we could do the following:

        pico.registerComponentImplementation("myDao", DaoImpl.class);
        pico.registerInterceptor(cuts.component("myDao"), cuts.allMethods(), logger);

Note that components and aspects can be registered in any order. An aspect can be registered before the component it applies to. In the example above, we could have reversed the two lines and registered the interceptor before the component.

#### Container Supplied Advice

Advice objects may themselves be components in the `PicoContainer`, with dependencies on other components. Let's revise our `LoggingInterceptor` to have a dependency on a log object of some sort. For simplicity, we'll just use a `StringBuffer` as our logger (in real life it might be a log4j or a commons logging object of some sort):

        public class LoggingInterceptor {
            private final StringBuffer log;

            public LoggingInterceptor(StringBuffer log) {
                this.log = log;
            }

            public Object invoke(MethodInvocation invocation) throws Throwable {
                log.append("start");
                Object result = invocation.proceed();
                log.append("end");
                return result;
            }
        }

With this in place, we could then register our `LoggingInterceptor` and apply it to a component as follows:

        // register dependency of LoggingInterceptor:
        pico.registerComponentInstance("log", StringBuffer.log);

        pico.registerComponentImplementation("logger", LoggingInterceptor.class);
        pico.registerComponentImplementation("myDao", DaoImpl.class);

        // you can specify the component key of the advice object:
        pico.registerInterceptor(cuts.component("myDao"), cuts.allMethods(), "logger");

Pico will supply the `StringBuffer` "log" component to the constructor of the `LoggingInterceptor`.

Mixins are a special case. While you can register a mixin as an explicit component in the container, you usually don't want to. Applying the same mixin instance as advice to multiple components would in effect mean that multiple components would share the same base class object - sharing the same instances variables, etc. This is usually not a good thing. However, you may specify a mixin class that has dependencies on components in the container. The container will instantiate a new mixin object for each component that it applies the mixin to, but will satisfy any dependencies the mixin has from components in the container, using constructor injection.

#### Pointcuts

Notice the use of the `PointcutsFactory`, `cuts`, in the first example. This interface provides methods for producing pointcuts that match one class or method, or that match the class, method or component name against a regular expressionm, pointcuts that pick all instances of a given class, or all classes in a given package, etc. You are not limited to the pointcuts produced by `PointcutsFactory` however. Any pointcut that implements one of the interfaces `ComponentPointcut`, `ClassPointcut`, `MethodPointcut` will work. Class pointcuts match against the component's class. Component pointcuts match against the component key. Method pointcuts match against the method being invoked. Method pointcuts only apply to interceptor advice; they are not used for mixins.

### Groovy Configuration

To configure aspects using groovy, use `org.nanocontainer.aop.script.groovy.DynaopNanoContainerBuilder`.

## Limitations

Components that have aspects applied to them must implement an interface. Advice is not applied to components registered via `registerComponentInstance`, or for components supplied via a custom `ComponentAdapter`.

Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES

Copyright © 2003-2007 Codehaus. All Rights Reserved.