loading table of contents...

5.2. Aspects

Aspects are a feature that allows you to add new functionality to existing content beans without modifying the content bean source code itself, either because the content bean source code is not available, or to create a reusable extension. When access to the content bean source code is available, using aspects is usually not necessary.

Terminology

Beans designed for extension by aspects are called aspect aggregators and implement the com.coremedia.cae.aspect.AspectAggregator interface. Typically, these will be content beans, extending com.coremedia.cae.aspect.contentbean.AbstractAspectAggregatorContentBean, but this is not a requirement. In the sections to follow, it is assumed your aspect aggregators are content beans.

An aspect is a bean to be "attached" to or associated with an aspect aggregator. Aspects have a name, and an aspect aggregator instance can have at most one aspect bean with a given name associated with it.

Setting up the Aspect Infrastructure

Aspect aggregators must implement the com.coremedia.cae.aspect.AspectAggregator interface. To make existing content beans aspect aware, make sure that they inherit from AbstractAspectAggregatorContentBean (rather than AbstractContentBean) and adjust your parent content bean definitions. Also, aspect aggregators need an AspectsProvider. The CompoundAspectsProvider in this example serves as a registry for plugins adding aspects to your content beans.

<bean id="aspectsProviders" class="org.springframework.beans.factory.config.ListFactoryBean">
  <property name="sourceList">
    <list value-type="com.coremedia.cae.aspect.provider.AspectsProvider"/>
  </property>
</bean>

<bean id="aspectsProvider" class="com.coremedia.cae.aspect.provider.CompoundAspectsProvider">
  <property name="aspectsProviders" ref="aspectsProviders"/>
</bean>

<bean id="contentBeanBase" abstract="true" class="AbstractAspectAggregatorContentBean">
  <property name="aspectsProvider" ref="aspectsProvider"/>
</bean>

<bean id="contentBeanFactory:YourType" class="com.yourcompany.YourTypeContentBean" parent="contentBeanBase">
  ...
</bean>

Example 5.1. Add aspect support to content beans


Registering Aspects

To create a new aspect, implement the Aspect interface and add the new behavior to this class, by adding bean properties, for instance. Choose an adequate AspectsProvider to provide instances of these beans. For instance, for an aspect to be added to content beans, choose the ContentBeanAspectsProvider. This provider needs its own content bean factory instance whose configuration will determine which content types the aspect should apply to.

<!-- factory to create aspect bean instances -->
<bean id="myAspectContentBeanFactory"
      class="com.coremedia.objectserver.beans.SpringContentBeanFactory"/>

<!-- configuration to map MyDoctype to MyDoctypeAspectContentBean -->
<bean name="myAspectContentBeanFactory:MyDoctype"
      class="com.mycompany.MyDoctypeAspectContentBean"
      scope="prototype">
  <property name="aggregatorContentBeanFactory"
            ref="contentBeanFactory"/>
</bean>

<!-- aspects provider for the new aspect -->
<bean id="myAspectsProvider"
      class="com.coremedia.cae.aspect.provider.ContentBeanAspectsProvider">
  <property name="contentBeanFactory"
            ref="myAspectContentBeanFactory"/>
</bean>

<!-- register the aspects provider -->
<customize:append id="addMyAspectProvider" bean="aspectsProviders">
  <list>
    <ref bean="myAspectsProvider"/>
  </list>
</customize>

Example 5.2. Registering an aspects provider for content beans


On the other hand, to add aspects to arbitrary Java beans which are not content beans, use a BeanFactoryAspectProvider instead. The aspect implementation class should also implement the AspectAggregatorAware interface to have access to the aspect aggregator. Define your aspect bean as a prototype bean with name like beanNameOfAspectProvider:classNameOfAggregatorBean where "classNameOfAggregatorBean" is the fully qualified class name of the bean the aspect will be applied to. You might use super classes or interfaces here as well.

<bean id="myAspectsProvider"
      class="com.coremedia.cae.aspect.provider.BeanFactoryAspectsProvider"/>

<bean name="myAspectContentBeanFactory:com.mycompany.MyBean"
      class="com.mycompany.MyBeanAspectImpl" scope="prototype">
  ...
</bean>

Example 5.3. Definition of an aspects provider for arbitrary Java beans


Working with Aspects

Aspects added to aggregator beans by an aspects provider are available in code by calling the getAspects or getAspectsByName methods:

Collection<? extends Aspect> aspects = contentBean.getAspects();
Map<String, ? extends Aspect> aspectsByName = contentBean.getAspectsByName();

In templates, use the map returned by getAspectsByName to access an aspect of the aggregator by its name:

self.aspectByName['myAspect'].myProperty