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