123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- <chapter id="pertypewithin" xreflabel="pertypewithin">
-
- <title>The pertypewithin Aspect Instantiation Model</title>
-
- <para>
- AspectJ 5 defines a new per-clause type for aspect instantiation:
- <literal>pertypewithin</literal>. Unlike the other per-clauses,
- <literal>pertypewithin</literal> takes a type pattern:
- </para>
-
- <programlisting><![CDATA[
- PerTypeWithin := 'pertypewithin' '(' OptionalParensTypePattern ')'
- ]]></programlisting>
-
- <para>
- When an aspect is declared using the <literal>pertypewithin</literal>
- instantiation model, one new aspect instance will be created for each
- type matched by the associated type pattern.
- </para>
-
- <para>
- Pertypewithin aspects have <literal>aspectOf</literal> and
- <literal>hasAspect</literal> methods with the following signatures:
- </para>
-
- <programlisting><![CDATA[
- /**
- * return true if this aspect has an instance associated with
- * the given type.
- */
- public static boolean hasAspect(Class clazz)
-
- /**
- * return the instance associated with the given type.
- * Throws NoAspectBoundException if there is no such
- * aspect.
- */
- public static P aspectOf(Class clazz)
- ]]></programlisting>
-
- <para>
- Where <literal>P</literal> is the type of the <literal>pertypewithin</literal>
- aspect.
- </para>
-
- <para>
- In common with the other per-clause instantiation models, the execution
- of any advice declared within a <literal>pertypewithin</literal> aspect
- is conditional upon an implicit pointcut condition. In this case, that
- any join point be <literal>within</literal> the type that the executing
- aspect is an <literal>aspectOf</literal>. For example, given the aspect
- definition
- </para>
-
- <programlisting><![CDATA[
- public aspect InstanceTracking pertypewithin(org.xyz..*) {
-
- private Set<WeakReference<Object>> instances = new HashSet<WeakReference<Object>>();
-
- after(Object o) returning : execution(new(..)) {
- instances.add(new WeakReference<Object>(o);
- }
-
- public Set<Object> getInstances() {
- Set<Object> result = new HashSet<Object>();
- for(WeakReference<Object> ref : instances) {
- if (ref.get() != null) {
- result.add(ref.get());
- }
- }
- return result;
- }
- }
- ]]></programlisting>
-
- <para>
- Then one aspect instance will be created for each type within
- <literal>org.xyz..*</literal>. For each aspect instance, the
- after returning advice will match only the execution of constructors
- in the type that the aspect is an instance of. The net result is that
- the aspect tracks all known instances of each type within
- <literal>org.xyz..*</literal>. To get access to the instances, a
- programmer can simply write
- <literal>InstanceTracking.instanceOf(org.xyz.SomeType).getInstances()</literal>.
- </para>
-
- <para>
- A <literal>pertypewithin</literal> aspect may optionally be declared
- with a single generic type parameter. In this case, for each type
- <literal>T</literal> matched by the type pattern, the aspect instance
- created will be of type <literal>PerTypeWithinAspect<T></literal>.
- So the previous example could also be written as:
- </para>
-
- <programlisting><![CDATA[
- public aspect InstanceTracking<T> pertypewithin(org.xyz..*) {
-
- private Set<WeakReference<T>> instances = new HashSet<WeakReference<T>>();
-
- after(T t) returning : execution(new(..)) {
- instances.add(new WeakReference<T>(t);
- }
-
- public Set<T> getInstances() {
- Set<T> result = new HashSet<T>();
- for(WeakReference<T> ref : instances) {
- if (ref.get() != null) {
- result.add(ref.get());
- }
- }
- return result;
- }
- }
- ]]></programlisting>
-
- <para>
- The <literal>pertypewithin</literal> aspect instantiation model should
- be used when the implementation of a crosscutting concern requires that
- some state be maintained for each type in a set of types. To maintain
- state for a single type, it is easier to use a static inter-type declared
- field. Examples of usage include instance tracking, profiling, and the
- implementation of a common tracing idiom that uses one Logger per
- traced class.
- </para>
- </chapter>
|