summaryrefslogtreecommitdiffstats
path: root/docs/adk15ProgGuideDB/pertypewithin.xml
blob: 4a5e9bbab46b92e71bfdf34d669db2ebbf94e492 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
<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 addition, <literal>pertypewithin</literal> aspects have a 
      <literal>getWithinTypeName</literal> method that can be called
      to return the package qualified name of the type for which the
      aspect instance has been created.
   </para>
   
   <programlisting><![CDATA[
    /**
     * return the package qualified name (eg. com.foo.MyClass) of the type
     * for which the aspect instance has been instantiated.
     */
     public String getWithinTypeName()
    ]]></programlisting>
   
   <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[
     import java.util.*;
     
     public aspect InstanceTracking pertypewithin(org.xyz..*) {
     
       // use WeakHashMap for auto-garbage collection of keys  	 
       private Map<Object,Boolean> instances = new WeakHashMap<Object,Boolean>();

       after(Object o) returning() : execution(new(..)) && this(o) {
         instances.put(o,true);
       }

       public Set<?> getInstances() {
         return instances.keySet();
       }
       
     } 
	]]></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
	    within the matched per-type-within type. 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.aspectOf(org.xyz.SomeType.class).getInstances()</literal>.
	</para>
  
    <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>