Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

gettingstarted.xml 50KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311
  1. <chapter id="starting" xreflabel="Getting Started with AspectJ">
  2. <title>Getting Started with AspectJ</title>
  3. <sect1 id="starting-intro">
  4. <title>Introduction</title>
  5. <para>
  6. Many software developers are attracted to the idea of aspect-oriented
  7. programming (AOP) but unsure about how to begin using the
  8. technology. They recognize the concept of crosscutting concerns, and
  9. know that they have had problems with the implementation of such
  10. concerns in the past. But there are many questions about how to adopt
  11. AOP into the development process. Common questions include:
  12. <itemizedlist spacing="compact">
  13. <listitem>
  14. <para>Can I use aspects in my existing code?</para>
  15. </listitem>
  16. <listitem>
  17. <para>
  18. What kinds of benefits can I expect to get from using aspects?
  19. </para>
  20. </listitem>
  21. <listitem>
  22. <para>How do I find aspects in my programs?</para>
  23. </listitem>
  24. <listitem>
  25. <para>How steep is the learning curve for AOP?</para>
  26. </listitem>
  27. <listitem>
  28. <para>What are the risks of using this new technology?</para>
  29. </listitem>
  30. </itemizedlist>
  31. </para>
  32. <para>
  33. This chapter addresses these questions in the context of AspectJ: a
  34. general-purpose aspect-oriented extension to Java. A series of
  35. abridged examples illustrate the kinds of aspects programmers may
  36. want to implement using AspectJ and the benefits associated with
  37. doing so. Readers who would like to understand the examples in more
  38. detail, or who want to learn how to program examples like these, can
  39. find more complete examples and supporting material linked from the
  40. AspectJ web site ( <ulink url="http://eclipse.org/aspectj" /> ).
  41. </para>
  42. <para>
  43. A significant risk in adopting any new technology is going too far
  44. too fast. Concern about this risk causes many organizations to be
  45. conservative about adopting new technology. To address this issue,
  46. the examples in this chapter are grouped into three broad categories,
  47. with aspects that are easier to adopt into existing development
  48. projects coming earlier in this chapter. The next section, <xref
  49. linkend="starting-aspectj"/>, we present the core of AspectJ's
  50. features, and in <xref linkend="starting-development"/>, we present
  51. aspects that facilitate tasks such as debugging, testing and
  52. performance tuning of applications. And, in the section following,
  53. <xref linkend="starting-production"/>, we present aspects that
  54. implement crosscutting functionality common in Java applications. We
  55. will defer discussing a third category of aspects, reusable aspects,
  56. until <xref linkend="language"/>.
  57. </para>
  58. <para>
  59. These categories are informal, and this ordering is not the only way
  60. to adopt AspectJ. Some developers may want to use a production aspect
  61. right away. But our experience with current AspectJ users suggests
  62. that this is one ordering that allows developers to get experience
  63. with (and benefit from) AOP technology quickly, while also minimizing
  64. risk.
  65. </para>
  66. </sect1>
  67. <sect1 id="starting-aspectj" xreflabel="Introduction to AspectJ">
  68. <title>Introduction to AspectJ</title>
  69. <para>
  70. This section presents a brief introduction to the features of AspectJ
  71. used later in this chapter. These features are at the core of the
  72. language, but this is by no means a complete overview of AspectJ.
  73. </para>
  74. <para>
  75. The features are presented using a simple figure editor system. A
  76. <classname>Figure</classname> consists of a number of
  77. <classname>FigureElements</classname>, which can be either
  78. <classname>Point</classname>s or <classname>Line</classname>s. The
  79. <classname>Figure</classname> class provides factory services. There
  80. is also a <classname>Display</classname>. Most example programs later
  81. in this chapter are based on this system as well.
  82. </para>
  83. <para>
  84. <mediaobject>
  85. <imageobject>
  86. <imagedata fileref="figureUML.gif"/>
  87. </imageobject>
  88. <caption>
  89. <para>
  90. UML for the <literal>FigureEditor</literal> example
  91. </para>
  92. </caption>
  93. </mediaobject>
  94. </para>
  95. <para>
  96. The motivation for AspectJ (and likewise for aspect-oriented
  97. programming) is the realization that there are issues or concerns
  98. that are not well captured by traditional programming
  99. methodologies. Consider the problem of enforcing a security policy in
  100. some application. By its nature, security cuts across many of the
  101. natural units of modularity of the application. Moreover, the
  102. security policy must be uniformly applied to any additions as the
  103. application evolves. And the security policy that is being applied
  104. might itself evolve. Capturing concerns like a security policy in a
  105. disciplined way is difficult and error-prone in a traditional
  106. programming language.
  107. </para>
  108. <para>
  109. Concerns like security cut across the natural units of
  110. modularity. For object-oriented programming languages, the natural
  111. unit of modularity is the class. But in object-oriented programming
  112. languages, crosscutting concerns are not easily turned into classes
  113. precisely because they cut across classes, and so these aren't
  114. reusable, they can't be refined or inherited, they are spread through
  115. out the program in an undisciplined way, in short, they are difficult
  116. to work with.
  117. </para>
  118. <para>
  119. Aspect-oriented programming is a way of modularizing crosscutting
  120. concerns much like object-oriented programming is a way of
  121. modularizing common concerns. AspectJ is an implementation of
  122. aspect-oriented programming for Java.
  123. </para>
  124. <para>
  125. AspectJ adds to Java just one new concept, a join point -- and that's
  126. really just a name for an existing Java concept. It adds to Java
  127. only a few new constructs: pointcuts, advice, inter-type declarations
  128. and aspects. Pointcuts and advice dynamically affect program flow,
  129. inter-type declarations statically affects a program's class
  130. hierarchy, and aspects encapsulate these new constructs.
  131. </para>
  132. <para>
  133. A <emphasis>join point</emphasis> is a well-defined point in the
  134. program flow. A <emphasis>pointcut</emphasis> picks out certain join
  135. points and values at those points. A piece of
  136. <emphasis>advice</emphasis> is code that is executed when a join
  137. point is reached. These are the dynamic parts of AspectJ.
  138. </para>
  139. <para>
  140. AspectJ also has different kinds of <emphasis>inter-type
  141. declarations</emphasis> that allow the programmer to modify a
  142. program's static structure, namely, the members of its classes and
  143. the relationship between classes.
  144. </para>
  145. <para>
  146. AspectJ's <emphasis>aspect</emphasis> are the unit of modularity for
  147. crosscutting concerns. They behave somewhat like Java classes, but
  148. may also include pointcuts, advice and inter-type declarations.
  149. </para>
  150. <para>
  151. In the sections immediately following, we are first going to look at
  152. join points and how they compose into pointcuts. Then we will look at
  153. advice, the code which is run when a pointcut is reached. We will see
  154. how to combine pointcuts and advice into aspects, AspectJ's reusable,
  155. inheritable unit of modularity. Lastly, we will look at how to use
  156. inter-type declarations to deal with crosscutting concerns of a
  157. program's class structure.
  158. </para>
  159. <!-- ============================== -->
  160. <sect2 id="the-dynamic-join-point-model" xreflabel="the-dynamic-join-point-model">
  161. <title>The Dynamic Join Point Model</title>
  162. <para>
  163. A critical element in the design of any aspect-oriented language is
  164. the join point model. The join point model provides the common
  165. frame of reference that makes it possible to define the dynamic
  166. structure of crosscutting concerns. This chapter describes
  167. AspectJ's dynamic join points, in which join points are certain
  168. well-defined points in the execution of the program.
  169. </para>
  170. <para>
  171. AspectJ provides for many kinds of join points, but this chapter
  172. discusses only one of them: method call join points. A method call
  173. join point encompasses the actions of an object receiving a method
  174. call. It includes all the actions that comprise a method call,
  175. starting after all arguments are evaluated up to and including
  176. return (either normally or by throwing an exception).
  177. </para>
  178. <para>
  179. Each method call at runtime is a different join point, even if it
  180. comes from the same call expression in the program. Many other
  181. join points may run while a method call join point is executing --
  182. all the join points that happen while executing the method body,
  183. and in those methods called from the body. We say that these join
  184. points execute in the <emphasis>dynamic context</emphasis> of the
  185. original call join point.
  186. </para>
  187. </sect2>
  188. <!-- ============================== -->
  189. <sect2 id="pointcuts-starting" xreflabel="pointcuts-starting">
  190. <title>Pointcuts</title>
  191. <para>
  192. In AspectJ, <emphasis>pointcuts</emphasis> pick out certain join
  193. points in the program flow. For example, the pointcut
  194. </para>
  195. <programlisting format="linespecific">
  196. call(void Point.setX(int))
  197. </programlisting>
  198. <para>
  199. picks out each join point that is a call to a method that has the
  200. signature <literal>void Point.setX(int)</literal> &mdash; that is,
  201. <classname>Point</classname>'s void <function>setX</function>
  202. method with a single <literal>int</literal> parameter.
  203. </para>
  204. <para>
  205. A pointcut can be built out of other pointcuts with and, or, and
  206. not (spelled <literal>&amp;&amp;</literal>, <literal>||</literal>,
  207. and <literal>!</literal>). For example:
  208. </para>
  209. <programlisting format="linespecific">
  210. call(void Point.setX(int)) ||
  211. call(void Point.setY(int))
  212. </programlisting>
  213. <para>
  214. picks out each join point that is either a call to
  215. <function>setX</function> or a call to <function>setY</function>.
  216. </para>
  217. <para>
  218. Pointcuts can identify join points from many different types
  219. &mdash; in other words, they can crosscut types. For example,
  220. </para>
  221. <programlisting format="linespecific">
  222. call(void FigureElement.setXY(int,int)) ||
  223. call(void Point.setX(int)) ||
  224. call(void Point.setY(int)) ||
  225. call(void Line.setP1(Point)) ||
  226. call(void Line.setP2(Point));
  227. </programlisting>
  228. <para>
  229. picks out each join point that is a call to one of five methods
  230. (the first of which is an interface method, by the way).
  231. </para>
  232. <para>
  233. In our example system, this pointcut captures all the join points
  234. when a <classname>FigureElement</classname> moves. While this is a
  235. useful way to specify this crosscutting concern, it is a bit of a
  236. mouthful. So AspectJ allows programmers to define their own named
  237. pointcuts with the <literal>pointcut</literal> form. So the
  238. following declares a new, named pointcut:
  239. </para>
  240. <programlisting format="linespecific">
  241. pointcut move():
  242. call(void FigureElement.setXY(int,int)) ||
  243. call(void Point.setX(int)) ||
  244. call(void Point.setY(int)) ||
  245. call(void Line.setP1(Point)) ||
  246. call(void Line.setP2(Point));
  247. </programlisting>
  248. <para>
  249. and whenever this definition is visible, the programmer can simply
  250. use <literal>move()</literal> to capture this complicated
  251. pointcut.
  252. </para>
  253. <para>
  254. The previous pointcuts are all based on explicit enumeration of a
  255. set of method signatures. We sometimes call this
  256. <emphasis>name-based</emphasis> crosscutting. AspectJ also
  257. provides mechanisms that enable specifying a pointcut in terms of
  258. properties of methods other than their exact name. We call this
  259. <emphasis>property-based</emphasis> crosscutting. The simplest of
  260. these involve using wildcards in certain fields of the method
  261. signature. For example, the pointcut
  262. </para>
  263. <programlisting format="linespecific">
  264. call(void Figure.make*(..))
  265. </programlisting>
  266. <para>
  267. picks out each join point that's a call to a void method defined
  268. on <classname>Figure</classname> whose the name begins with
  269. "<literal>make</literal>" regardless of the method's parameters.
  270. In our system, this picks out calls to the factory methods
  271. <function>makePoint</function> and <function>makeLine</function>.
  272. The pointcut
  273. </para>
  274. <programlisting format="linespecific">
  275. call(public * Figure.* (..))
  276. </programlisting>
  277. <para>
  278. picks out each call to <classname>Figure</classname>'s public
  279. methods.
  280. </para>
  281. <para>
  282. But wildcards aren't the only properties AspectJ supports.
  283. Another pointcut, <function>cflow</function>, identifies join
  284. points based on whether they occur in the dynamic context of
  285. other join points. So
  286. </para>
  287. <programlisting format="linespecific">
  288. cflow(move())
  289. </programlisting>
  290. <para>
  291. picks out each join point that occurs in the dynamic context of
  292. the join points picked out by <literal>move()</literal>, our named
  293. pointcut defined above. So this picks out each join points that
  294. occurrs between when a move method is called and when it returns
  295. (either normally or by throwing an exception).
  296. </para>
  297. </sect2>
  298. <!-- ============================== -->
  299. <sect2 id="advice-starting" xreflabel="advice-starting">
  300. <title>Advice</title>
  301. <para>
  302. So pointcuts pick out join points. But they don't
  303. <emphasis>do</emphasis> anything apart from picking out join
  304. points. To actually implement crosscutting behavior, we use
  305. advice. Advice brings together a pointcut (to pick out join
  306. points) and a body of code (to run at each of those join points).
  307. </para>
  308. <para>
  309. AspectJ has several different kinds of advice. <emphasis>Before
  310. advice</emphasis> runs as a join point is reached, before the
  311. program proceeds with the join point. For example, before advice
  312. on a method call join point runs before the actual method starts
  313. running, just after the arguments to the method call are evaluated.
  314. </para>
  315. <programlisting><![CDATA[
  316. before(): move() {
  317. System.out.println("about to move");
  318. }
  319. ]]></programlisting>
  320. <para>
  321. <emphasis>After advice</emphasis> on a particular join point runs
  322. after the program proceeds with that join point. For example,
  323. after advice on a method call join point runs after the method body
  324. has run, just before before control is returned to the caller.
  325. Because Java programs can leave a join point 'normally' or by
  326. throwing an exception, there are three kinds of after advice:
  327. <literal>after returning</literal>, <literal>after
  328. throwing</literal>, and plain <literal>after</literal> (which runs
  329. after returning <emphasis>or</emphasis> throwing, like Java's
  330. <literal>finally</literal>).
  331. </para>
  332. <programlisting><![CDATA[
  333. after() returning: move() {
  334. System.out.println("just successfully moved");
  335. }
  336. ]]></programlisting>
  337. <para>
  338. <emphasis>Around advice</emphasis> on a join point runs as the join
  339. point is reached, and has explicit control over whether the program
  340. proceeds with the join point. Around advice is not discussed in
  341. this section.
  342. </para>
  343. <sect3>
  344. <title>Exposing Context in Pointcuts</title>
  345. <para>
  346. Pointcuts not only pick out join points, they can also expose
  347. part of the execution context at their join points. Values
  348. exposed by a pointcut can be used in the body of advice
  349. declarations.
  350. </para>
  351. <para>
  352. An advice declaration has a parameter list (like a method) that
  353. gives names to all the pieces of context that it uses. For
  354. example, the after advice
  355. </para>
  356. <programlisting><![CDATA[
  357. after(FigureElement fe, int x, int y) returning:
  358. ...SomePointcut... {
  359. ...SomeBody...
  360. }
  361. ]]></programlisting>
  362. <para>
  363. uses three pieces of exposed context, a
  364. <literal>FigureElement</literal> named fe, and two
  365. <literal>int</literal>s named x and y.
  366. </para>
  367. <para>
  368. The body of the advice uses the names just like method
  369. parameters, so
  370. </para>
  371. <programlisting><![CDATA[
  372. after(FigureElement fe, int x, int y) returning:
  373. ...SomePointcut... {
  374. System.out.println(fe + " moved to (" + x + ", " + y + ")");
  375. }
  376. ]]></programlisting>
  377. <para>
  378. The advice's pointcut publishes the values for the advice's
  379. arguments. The three primitive pointcuts
  380. <literal>this</literal>, <literal>target</literal> and
  381. <literal>args</literal> are used to publish these values. So now
  382. we can write the complete piece of advice:
  383. </para>
  384. <programlisting><![CDATA[
  385. after(FigureElement fe, int x, int y) returning:
  386. call(void FigureElement.setXY(int, int))
  387. && target(fe)
  388. && args(x, y) {
  389. System.out.println(fe + " moved to (" + x + ", " + y + ")");
  390. }
  391. ]]></programlisting>
  392. <para>
  393. The pointcut exposes three values from calls to
  394. <function>setXY</function>: the target
  395. <classname>FigureElement</classname> -- which it publishes as
  396. <literal>fe</literal>, so it becomes the first argument to the
  397. after advice -- and the two int arguments -- which it publishes
  398. as <literal>x</literal> and <literal>y</literal>, so they become
  399. the second and third argument to the after advice.
  400. </para>
  401. <para>
  402. So the advice prints the figure element
  403. that was moved and its new <literal>x</literal> and
  404. <literal>y</literal> coordinates after each
  405. <classname>setXY</classname> method call.
  406. </para>
  407. <para>
  408. A named pointcut may have parameters like a piece of advice.
  409. When the named pointcut is used (by advice, or in another named
  410. pointcut), it publishes its context by name just like the
  411. <literal>this</literal>, <literal>target</literal> and
  412. <literal>args</literal> pointcut. So another way to write the
  413. above advice is
  414. </para>
  415. <programlisting><![CDATA[
  416. pointcut setXY(FigureElement fe, int x, int y):
  417. call(void FigureElement.setXY(int, int))
  418. && target(fe)
  419. && args(x, y);
  420. after(FigureElement fe, int x, int y) returning: setXY(fe, x, y) {
  421. System.out.println(fe + " moved to (" + x + ", " + y + ").");
  422. }
  423. ]]></programlisting>
  424. </sect3>
  425. </sect2>
  426. <!-- ============================== -->
  427. <sect2 id="inter-type-declarations" xreflabel="inter-type-declarations">
  428. <title>Inter-type declarations</title>
  429. <para>
  430. Inter-type declarations in AspectJ are declarations that cut across
  431. classes and their hierarchies. They may declare members that cut
  432. across multiple classes, or change the inheritance relationship
  433. between classes. Unlike advice, which operates primarily
  434. dynamically, introduction operates statically, at compile-time.
  435. </para>
  436. <para>
  437. Consider the problem of expressing a capability shared by some
  438. existing classes that are already part of a class hierarchy,
  439. i.e. they already extend a class. In Java, one creates an
  440. interface that captures this new capability, and then adds to
  441. <emphasis>each affected class</emphasis> a method that implements
  442. this interface.
  443. </para>
  444. <para>
  445. AspectJ can express the concern in one place, by using inter-type
  446. declarations. The aspect declares the methods and fields that are
  447. necessary to implement the new capability, and associates the
  448. methods and fields to the existing classes.
  449. </para>
  450. <para>
  451. Suppose we want to have <classname>Screen</classname> objects
  452. observe changes to <classname>Point</classname> objects, where
  453. <classname>Point</classname> is an existing class. We can implement
  454. this by writing an aspect declaring that the class Point
  455. <classname>Point</classname> has an instance field,
  456. <varname>observers</varname>, that keeps track of the
  457. <classname>Screen</classname> objects that are observing
  458. <classname>Point</classname>s.
  459. </para>
  460. <programlisting><![CDATA[
  461. aspect PointObserving {
  462. private Vector Point.observers = new Vector();
  463. ...
  464. }
  465. ]]></programlisting>
  466. <para>
  467. The <literal>observers</literal> field is private, so only
  468. <classname>PointObserving</classname> can see it. So observers are
  469. added or removed with the static methods
  470. <function>addObserver</function> and
  471. <function>removeObserver</function> on the aspect.
  472. </para>
  473. <programlisting><![CDATA[
  474. aspect PointObserving {
  475. private Vector Point.observers = new Vector();
  476. public static void addObserver(Point p, Screen s) {
  477. p.observers.add(s);
  478. }
  479. public static void removeObserver(Point p, Screen s) {
  480. p.observers.remove(s);
  481. }
  482. ...
  483. }
  484. ]]></programlisting>
  485. <para>
  486. Along with this, we can define a pointcut
  487. <function>changes</function> that defines what we want to observe,
  488. and the after advice defines what we want to do when we observe a
  489. change.
  490. </para>
  491. <programlisting><![CDATA[
  492. aspect PointObserving {
  493. private Vector Point.observers = new Vector();
  494. public static void addObserver(Point p, Screen s) {
  495. p.observers.add(s);
  496. }
  497. public static void removeObserver(Point p, Screen s) {
  498. p.observers.remove(s);
  499. }
  500. pointcut changes(Point p): target(p) && call(void Point.set*(int));
  501. after(Point p): changes(p) {
  502. Iterator iter = p.observers.iterator();
  503. while ( iter.hasNext() ) {
  504. updateObserver(p, (Screen)iter.next());
  505. }
  506. }
  507. static void updateObserver(Point p, Screen s) {
  508. s.display(p);
  509. }
  510. }
  511. ]]></programlisting>
  512. <para>
  513. Note that neither <classname>Screen</classname>'s nor
  514. <classname>Point</classname>'s code has to be modified, and that
  515. all the changes needed to support this new capability are local to
  516. this aspect.
  517. </para>
  518. </sect2>
  519. <!-- ============================== -->
  520. <sect2 id="aspects" xreflabel="aspects">
  521. <title>Aspects</title>
  522. <para>
  523. Aspects wrap up pointcuts, advice, and inter-type declarations in a
  524. a modular unit of crosscutting implementation. It is defined very
  525. much like a class, and can have methods, fields, and initializers
  526. in addition to the crosscutting members. Because only aspects may
  527. include these crosscutting members, the declaration of these
  528. effects is localized.
  529. </para>
  530. <para>
  531. Like classes, aspects may be instantiated, but AspectJ controls how
  532. that instantiation happens -- so you can't use Java's
  533. <literal>new</literal> form to build new aspect instances. By
  534. default, each aspect is a singleton, so one aspect instance is
  535. created. This means that advice may use non-static fields of the
  536. aspect, if it needs to keep state around:
  537. </para>
  538. <programlisting><![CDATA[
  539. aspect Logging {
  540. OutputStream logStream = System.err;
  541. before(): move() {
  542. logStream.println("about to move");
  543. }
  544. }
  545. ]]></programlisting>
  546. <para>
  547. Aspects may also have more complicated rules for instantiation, but
  548. these will be described in a later chapter.
  549. </para>
  550. </sect2>
  551. </sect1>
  552. <!-- ============================== -->
  553. <sect1 id="starting-development" xreflabel="Development Aspects">
  554. <title>Development Aspects</title>
  555. <para>
  556. The next two sections present the use of aspects in increasingly
  557. sophisticated ways. Development aspects are easily removed from
  558. production builds. Production aspects are intended to be used in
  559. both development and in production, but tend to affect only a few
  560. classes.
  561. </para>
  562. <para>
  563. This section presents examples of aspects that can be used during
  564. development of Java applications. These aspects facilitate debugging,
  565. testing and performance tuning work. The aspects define behavior that
  566. ranges from simple tracing, to profiling, to testing of internal
  567. consistency within the application. Using AspectJ makes it possible
  568. to cleanly modularize this kind of functionality, thereby making it
  569. possible to easily enable and disable the functionality when desired.
  570. </para>
  571. <sect2 id="tracing" xreflabel="tracing">
  572. <title>Tracing</title>
  573. <para>
  574. This first example shows how to increase the visibility of the
  575. internal workings of a program. It is a simple tracing aspect that
  576. prints a message at specified method calls. In our figure editor
  577. example, one such aspect might simply trace whenever points are
  578. drawn.
  579. </para>
  580. <programlisting><![CDATA[
  581. aspect SimpleTracing {
  582. pointcut tracedCall():
  583. call(void FigureElement.draw(GraphicsContext));
  584. before(): tracedCall() {
  585. System.out.println("Entering: " + thisJoinPoint);
  586. }
  587. }
  588. ]]></programlisting>
  589. <para>
  590. This code makes use of the <literal>thisJoinPoint</literal> special
  591. variable. Within all advice bodies this variable is bound to an
  592. object that describes the current join point. The effect of this
  593. code is to print a line like the following every time a figure
  594. element receives a <function>draw</function> method call:
  595. </para>
  596. <programlisting><![CDATA[
  597. Entering: call(void FigureElement.draw(GraphicsContext))
  598. ]]></programlisting>
  599. <para>
  600. To understand the benefit of coding this with AspectJ consider
  601. changing the set of method calls that are traced. With AspectJ,
  602. this just requires editing the definition of the
  603. <function>tracedCalls</function> pointcut and recompiling. The
  604. individual methods that are traced do not need to be edited.
  605. </para>
  606. <para>
  607. When debugging, programmers often invest considerable effort in
  608. figuring out a good set of trace points to use when looking for a
  609. particular kind of problem. When debugging is complete or appears
  610. to be complete it is frustrating to have to lose that investment by
  611. deleting trace statements from the code. The alternative of just
  612. commenting them out makes the code look bad, and can cause trace
  613. statements for one kind of debugging to get confused with trace
  614. statements for another kind of debugging.
  615. </para>
  616. <para>
  617. With AspectJ it is easy to both preserve the work of designing a
  618. good set of trace points and disable the tracing when it isn t
  619. being used. This is done by writing an aspect specifically for that
  620. tracing mode, and removing that aspect from the compilation when it
  621. is not needed.
  622. </para>
  623. <para>
  624. This ability to concisely implement and reuse debugging
  625. configurations that have proven useful in the past is a direct
  626. result of AspectJ modularizing a crosscutting design element the
  627. set of methods that are appropriate to trace when looking for a
  628. given kind of information.
  629. </para>
  630. </sect2>
  631. <sect2 id="profiling-and-logging" xreflabel="profiling-and-logging">
  632. <title>Profiling and Logging</title>
  633. <para>
  634. Our second example shows you how to do some very specific
  635. profiling. Although many sophisticated profiling tools are
  636. available, and these can gather a variety of information and
  637. display the results in useful ways, you may sometimes want to
  638. profile or log some very specific behavior. In these cases, it is
  639. often possible to write a simple aspect similar to the ones above
  640. to do the job.
  641. </para>
  642. <para>
  643. For example, the following aspect counts the number of calls to the
  644. <function>rotate</function> method on a <classname>Line</classname>
  645. and the number of calls to the <function>set*</function> methods of
  646. a <classname>Point</classname> that happen within the control flow
  647. of those calls to <function>rotate</function>:
  648. </para>
  649. <programlisting><![CDATA[
  650. aspect SetsInRotateCounting {
  651. int rotateCount = 0;
  652. int setCount = 0;
  653. before(): call(void Line.rotate(double)) {
  654. rotateCount++;
  655. }
  656. before(): call(void Point.set*(int))
  657. && cflow(call(void Line.rotate(double))) {
  658. setCount++;
  659. }
  660. }
  661. ]]></programlisting>
  662. <para>
  663. In effect, this aspect allows the programmer to ask very specific
  664. questions like
  665. <blockquote>
  666. How many times is the <function>rotate</function>
  667. method defined on <classname>Line</classname> objects called?
  668. </blockquote>
  669. and
  670. <blockquote>
  671. How many times are methods defined on
  672. <classname>Point</classname> objects whose name begins with
  673. "<function>set</function>" called in fulfilling those rotate
  674. calls?
  675. </blockquote>
  676. questions it may be difficult to express using standard
  677. profiling or logging tools.
  678. </para>
  679. </sect2>
  680. <!-- ============================== -->
  681. <sect2 id="pre-and-post-conditions" xreflabel="pre-and-post-conditions">
  682. <title>Pre- and Post-Conditions</title>
  683. <para>
  684. Many programmers use the "Design by Contract" style popularized by
  685. Bertand Meyer in <citetitle>Object-Oriented Software Construction,
  686. 2/e</citetitle>. In this style of programming, explicit
  687. pre-conditions test that callers of a method call it properly and
  688. explicit post-conditions test that methods properly do the work
  689. they are supposed to.
  690. </para>
  691. <para>
  692. AspectJ makes it possible to implement pre- and post-condition
  693. testing in modular form. For example, this code
  694. </para>
  695. <programlisting><![CDATA[
  696. aspect PointBoundsChecking {
  697. pointcut setX(int x):
  698. (call(void FigureElement.setXY(int, int)) && args(x, *))
  699. || (call(void Point.setX(int)) && args(x));
  700. pointcut setY(int y):
  701. (call(void FigureElement.setXY(int, int)) && args(*, y))
  702. || (call(void Point.setY(int)) && args(y));
  703. before(int x): setX(x) {
  704. if ( x < MIN_X || x > MAX_X )
  705. throw new IllegalArgumentException("x is out of bounds.");
  706. }
  707. before(int y): setY(y) {
  708. if ( y < MIN_Y || y > MAX_Y )
  709. throw new IllegalArgumentException("y is out of bounds.");
  710. }
  711. }
  712. ]]></programlisting>
  713. <para>
  714. implements the bounds checking aspect of pre-condition testing for
  715. operations that move points. Notice that the
  716. <function>setX</function> pointcut refers to all the operations
  717. that can set a Point's <literal>x</literal> coordinate; this
  718. includes the <function>setX</function> method, as well as half of
  719. the <function>setXY</function> method. In this sense the
  720. <function>setX</function> pointcut can be seen as involving very
  721. fine-grained crosscutting &mdash; it names the the
  722. <function>setX</function> method and half of the
  723. <function>setXY</function> method.
  724. </para>
  725. <para>
  726. Even though pre- and post-condition testing aspects can often be
  727. used only during testing, in some cases developers may wish to
  728. include them in the production build as well. Again, because
  729. AspectJ makes it possible to modularize these crosscutting concerns
  730. cleanly, it gives developers good control over this decision.
  731. </para>
  732. </sect2>
  733. <!-- ============================== -->
  734. <sect2 id="contract-enforcement" xreflabel="contract-enforcement">
  735. <title>Contract Enforcement</title>
  736. <para>
  737. The property-based crosscutting mechanisms can be very useful in
  738. defining more sophisticated contract enforcement. One very powerful
  739. use of these mechanisms is to identify method calls that, in a
  740. correct program, should not exist. For example, the following
  741. aspect enforces the constraint that only the well-known factory
  742. methods can add an element to the registry of figure
  743. elements. Enforcing this constraint ensures that no figure element
  744. is added to the registry more than once.
  745. </para>
  746. <programlisting><![CDATA[
  747. aspect RegistrationProtection {
  748. pointcut register(): call(void Registry.register(FigureElement));
  749. pointcut canRegister(): withincode(static * FigureElement.make*(..));
  750. before(): register() && !canRegister() {
  751. throw new IllegalAccessException("Illegal call " + thisJoinPoint);
  752. }
  753. }
  754. ]]></programlisting>
  755. <para>
  756. This aspect uses the withincode primitive pointcut to denote all
  757. join points that occur within the body of the factory methods on
  758. <classname>FigureElement</classname> (the methods with names that
  759. begin with "<literal>make</literal>"). This is a property-based
  760. pointcut because it identifies join points based not on their
  761. signature, but rather on the property that they occur specifically
  762. within the code of another method. The before advice declaration
  763. effectively says signal an error for any calls to register that are
  764. not within the factory methods.
  765. </para>
  766. <para>
  767. This advice throws a runtime exception at certain join points, but
  768. AspectJ can do better. Using the <literal>declare error</literal>
  769. form, we can have the <emphasis>compiler</emphasis> signal the
  770. error.
  771. </para>
  772. <programlisting><![CDATA[
  773. aspect RegistrationProtection {
  774. pointcut register(): call(void Registry.register(FigureElement));
  775. pointcut canRegister(): withincode(static * FigureElement.make*(..));
  776. declare error: register() && !canRegister(): "Illegal call"
  777. }
  778. ]]></programlisting>
  779. <para>
  780. When using this aspect, it is impossible for the compiler to
  781. compile programs with these illegal calls. This early detection is
  782. not always possible. In this case, since we depend only on static
  783. information (the <literal>withincode</literal> pointcut picks out
  784. join points totally based on their code, and the
  785. <literal>call</literal> pointcut here picks out join points
  786. statically). Other enforcement, such as the precondition
  787. enforcement, above, does require dynamic information such as the
  788. runtime value of parameters.
  789. </para>
  790. </sect2>
  791. <!-- ============================== -->
  792. <sect2 id="configuration-management" xreflabel="configuration-management">
  793. <title>Configuration Management</title>
  794. <para>
  795. Configuration management for aspects can be handled using a variety
  796. of make-file like techniques. To work with optional aspects, the
  797. programmer can simply define their make files to either include the
  798. aspect in the call to the AspectJ compiler or not, as desired.
  799. </para>
  800. <para>
  801. Developers who want to be certain that no aspects are included in
  802. the production build can do so by configuring their make files so
  803. that they use a traditional Java compiler for production builds. To
  804. make it easy to write such make files, the AspectJ compiler has a
  805. command-line interface that is consistent with ordinary Java
  806. compilers.
  807. </para>
  808. </sect2>
  809. </sect1>
  810. <!-- ============================== -->
  811. <sect1 id="starting-production" xreflabel="Production Aspects">
  812. <title>Production Aspects</title>
  813. <para>
  814. This section presents examples of aspects that are inherently
  815. intended to be included in the production builds of an application.
  816. Production aspects tend to add functionality to an application
  817. rather than merely adding more visibility of the internals of a
  818. program. Again, we begin with name-based aspects and follow with
  819. property-based aspects. Name-based production aspects tend to
  820. affect only a small number of methods. For this reason, they are a
  821. good next step for projects adopting AspectJ. But even though they
  822. tend to be small and simple, they can often have a significant
  823. effect in terms of making the program easier to understand and
  824. maintain.
  825. </para>
  826. <sect2 id="change-monitoring" xreflabel="change-monitoring">
  827. <title>Change Monitoring</title>
  828. <para>
  829. The first example production aspect shows how one might implement
  830. some simple functionality where it is problematic to try and do it
  831. explicitly. It supports the code that refreshes the display. The
  832. role of the aspect is to maintain a dirty bit indicating whether or
  833. not an object has moved since the last time the display was
  834. refreshed.
  835. </para>
  836. <para>
  837. Implementing this functionality as an aspect is straightforward.
  838. The <function>testAndClear</function> method is called by the
  839. display code to find out whether a figure element has moved
  840. recently. This method returns the current state of the dirty flag
  841. and resets it to false. The pointcut <function>move</function>
  842. captures all the method calls that can move a figure element. The
  843. after advice on <function>move</function> sets the dirty flag
  844. whenever an object moves.
  845. </para>
  846. <programlisting><![CDATA[
  847. aspect MoveTracking {
  848. private static boolean dirty = false;
  849. public static boolean testAndClear() {
  850. boolean result = dirty;
  851. dirty = false;
  852. return result;
  853. }
  854. pointcut move():
  855. call(void FigureElement.setXY(int, int)) ||
  856. call(void Line.setP1(Point)) ||
  857. call(void Line.setP2(Point)) ||
  858. call(void Point.setX(int)) ||
  859. call(void Point.setY(int));
  860. after() returning: move() {
  861. dirty = true;
  862. }
  863. }
  864. ]]></programlisting>
  865. <para>
  866. Even this simple example serves to illustrate some of the important
  867. benefits of using AspectJ in production code. Consider implementing
  868. this functionality with ordinary Java: there would likely be a
  869. helper class that contained the <literal>dirty</literal> flag, the
  870. <function>testAndClear</function> method, as well as a
  871. <function>setFlag</function> method. Each of the methods that could
  872. move a figure element would include a call to the
  873. <function>setFlag</function> method. Those calls, or rather the
  874. concept that those calls should happen at each move operation, are
  875. the crosscutting concern in this case.
  876. </para>
  877. <para>
  878. The AspectJ implementation has several advantages over the standard
  879. implementation:
  880. </para>
  881. <para>
  882. <emphasis>The structure of the crosscutting concern is captured
  883. explicitly.</emphasis> The moves pointcut clearly states all the
  884. methods involved, so the programmer reading the code sees not just
  885. individual calls to <literal>setFlag</literal>, but instead sees
  886. the real structure of the code. The IDE support included with
  887. AspectJ automatically reminds the programmer that this aspect
  888. advises each of the methods involved. The IDE support also
  889. provides commands to jump to the advice from the method and
  890. vice-versa.
  891. </para>
  892. <para>
  893. <emphasis>Evolution is easier.</emphasis> If, for example, the
  894. aspect needs to be revised to record not just that some figure
  895. element moved, but rather to record exactly which figure elements
  896. moved, the change would be entirely local to the aspect. The
  897. pointcut would be updated to expose the object being moved, and the
  898. advice would be updated to record that object. The paper
  899. <citetitle>An Overview of AspectJ</citetitle> (available linked off
  900. of the AspectJ web site -- <ulink
  901. url="http://eclipse.org/aspectj" />), presented at ECOOP
  902. 2001, presents a detailed discussion of various ways this aspect
  903. could be expected to evolve.
  904. </para>
  905. <para>
  906. <emphasis>The functionality is easy to plug in and out.</emphasis>
  907. Just as with development aspects, production aspects may need to be
  908. removed from the system, either because the functionality is no
  909. longer needed at all, or because it is not needed in certain
  910. configurations of a system. Because the functionality is
  911. modularized in a single aspect this is easy to do.
  912. </para>
  913. <para>
  914. <emphasis>The implementation is more stable.</emphasis> If, for
  915. example, the programmer adds a subclass of
  916. <classname>Line</classname> that overrides the existing methods,
  917. this advice in this aspect will still apply. In the ordinary Java
  918. implementation the programmer would have to remember to add the
  919. call to <function>setFlag</function> in the new overriding
  920. method. This benefit is often even more compelling for
  921. property-based aspects (see the section <xref
  922. linkend="starting-production-consistentBehavior"/>).
  923. </para>
  924. </sect2>
  925. <!-- ============================== -->
  926. <sect2 id="context-passing" xreflabel="context-passing">
  927. <title>Context Passing</title>
  928. <para>
  929. The crosscutting structure of context passing can be a significant
  930. source of complexity in Java programs. Consider implementing
  931. functionality that would allow a client of the figure editor (a
  932. program client rather than a human) to set the color of any figure
  933. elements that are created. Typically this requires passing a color,
  934. or a color factory, from the client, down through the calls that
  935. lead to the figure element factory. All programmers are familiar
  936. with the inconvenience of adding a first argument to a number of
  937. methods just to pass this kind of context information.
  938. </para>
  939. <para>
  940. Using AspectJ, this kind of context passing can be implemented in a
  941. modular way. The following code adds after advice that runs only
  942. when the factory methods of <classname>Figure</classname> are
  943. called in the control flow of a method on a
  944. <classname>ColorControllingClient</classname>.
  945. </para>
  946. <programlisting><![CDATA[
  947. aspect ColorControl {
  948. pointcut CCClientCflow(ColorControllingClient client):
  949. cflow(call(* * (..)) && target(client));
  950. pointcut make(): call(FigureElement Figure.make*(..));
  951. after (ColorControllingClient c) returning (FigureElement fe):
  952. make() && CCClientCflow(c) {
  953. fe.setColor(c.colorFor(fe));
  954. }
  955. }
  956. ]]></programlisting>
  957. <para>
  958. This aspect affects only a small number of methods, but note that
  959. the non-AOP implementation of this functionality might require
  960. editing many more methods, specifically, all the methods in the
  961. control flow from the client to the factory. This is a benefit
  962. common to many property-based aspects while the aspect is short and
  963. affects only a modest number of benefits, the complexity the aspect
  964. saves is potentially much larger.
  965. </para>
  966. </sect2>
  967. <!-- ============================== -->
  968. <sect2 id="starting-production-consistentBehavior" xreflabel="Providing Consistent Behavior">
  969. <title>Providing Consistent Behavior</title>
  970. <para>
  971. This example shows how a property-based aspect can be used to
  972. provide consistent handling of functionality across a large set of
  973. operations. This aspect ensures that all public methods of the
  974. <literal>com.bigboxco</literal> package log any Errors they throw
  975. to their caller (in Java, an Error is like an Exception, but it
  976. indicates that something really bad and usually unrecoverable has
  977. happened). The <function>publicMethodCall</function> pointcut
  978. captures the public method calls of the package, and the after
  979. advice runs whenever one of those calls throws an Error. The advice
  980. logs that Error and then the throw resumes.
  981. </para>
  982. <programlisting><![CDATA[
  983. aspect PublicErrorLogging {
  984. Log log = new Log();
  985. pointcut publicMethodCall():
  986. call(public * com.bigboxco.*.*(..));
  987. after() throwing (Error e): publicMethodCall() {
  988. log.write(e);
  989. }
  990. }
  991. ]]></programlisting>
  992. <para>
  993. In some cases this aspect can log an exception twice. This happens
  994. if code inside the <literal>com.bigboxco</literal> package itself
  995. calls a public method of the package. In that case this code will
  996. log the error at both the outermost call into the
  997. <literal>com.bigboxco</literal> package and the re-entrant
  998. call. The <function>cflow</function> primitive pointcut can be used
  999. in a nice way to exclude these re-entrant calls:</para>
  1000. <programlisting><![CDATA[
  1001. after() throwing (Error e):
  1002. publicMethodCall() && !cflow(publicMethodCall()) {
  1003. log.write(e);
  1004. }
  1005. ]]></programlisting>
  1006. <para>
  1007. The following aspect is taken from work on the AspectJ compiler.
  1008. The aspect advises about 35 methods in the
  1009. <classname>JavaParser</classname> class. The individual methods
  1010. handle each of the different kinds of elements that must be
  1011. parsed. They have names like <function>parseMethodDec</function>,
  1012. <function>parseThrows</function>, and
  1013. <function>parseExpr</function>.
  1014. </para>
  1015. <programlisting><![CDATA[
  1016. aspect ContextFilling {
  1017. pointcut parse(JavaParser jp):
  1018. call(* JavaParser.parse*(..))
  1019. && target(jp)
  1020. && !call(Stmt parseVarDec(boolean)); // var decs
  1021. // are tricky
  1022. around(JavaParser jp) returns ASTObject: parse(jp) {
  1023. Token beginToken = jp.peekToken();
  1024. ASTObject ret = proceed(jp);
  1025. if (ret != null) jp.addContext(ret, beginToken);
  1026. return ret;
  1027. }
  1028. }
  1029. ]]></programlisting>
  1030. <para>
  1031. This example exhibits a property found in many aspects with large
  1032. property-based pointcuts. In addition to a general property based
  1033. pattern <literal>call(* JavaParser.parse*(..))</literal> it
  1034. includes an exception to the pattern <literal>!call(Stmt
  1035. parseVarDec(boolean))</literal>. The exclusion of
  1036. <function>parseVarDec</function> happens because the parsing of
  1037. variable declarations in Java is too complex to fit with the clean
  1038. pattern of the other <function>parse*</function> methods. Even with
  1039. the explicit exclusion this aspect is a clear expression of a clean
  1040. crosscutting modularity. Namely that all
  1041. <function>parse*</function> methods that return
  1042. <classname>ASTObjects</classname>, except for
  1043. <function>parseVarDec</function> share a common behavior for
  1044. establishing the parse context of their result.
  1045. </para>
  1046. <para>
  1047. The process of writing an aspect with a large property-based
  1048. pointcut, and of developing the appropriate exceptions can clarify
  1049. the structure of the system. This is especially true, as in this
  1050. case, when refactoring existing code to use aspects. When we first
  1051. looked at the code for this aspect, we were able to use the IDE
  1052. support provided in AJDE for JBuilder to see what methods the
  1053. aspect was advising compared to our manual coding. We quickly
  1054. discovered that there were a dozen places where the aspect advice
  1055. was in effect but we had not manually inserted the required
  1056. functionality. Two of these were bugs in our prior non-AOP
  1057. implementation of the parser. The other ten were needless
  1058. performance optimizations. So, here, refactoring the code to
  1059. express the crosscutting structure of the aspect explicitly made
  1060. the code more concise and eliminated latent bugs.
  1061. </para>
  1062. </sect2>
  1063. </sect1>
  1064. <!-- ============================== -->
  1065. <sect1 id="starting-conclusion">
  1066. <title>Conclusion</title>
  1067. <para>
  1068. AspectJ is a simple and practical aspect-oriented extension to
  1069. Java. With just a few new constructs, AspectJ provides support for
  1070. modular implementation of a range of crosscutting concerns.
  1071. </para>
  1072. <para>
  1073. Adoption of AspectJ into an existing Java development project can be
  1074. a straightforward and incremental task. One path is to begin by using
  1075. only development aspects, going on to using production aspects and
  1076. then reusable aspects after building up experience with
  1077. AspectJ. Adoption can follow other paths as well. For example, some
  1078. developers will benefit from using production aspects right
  1079. away. Others may be able to write clean reusable aspects almost right
  1080. away.
  1081. </para>
  1082. <para>
  1083. AspectJ enables both name-based and property based crosscutting.
  1084. Aspects that use name-based crosscutting tend to affect a small
  1085. number of other classes. But despite their small scale, they can
  1086. often eliminate significant complexity compared to an ordinary Java
  1087. implementation. Aspects that use property-based crosscutting can
  1088. have small or large scale.
  1089. </para>
  1090. <para>
  1091. Using AspectJ results in clean well-modularized implementations of
  1092. crosscutting concerns. When written as an AspectJ aspect the
  1093. structure of a crosscutting concern is explicit and easy to
  1094. understand. Aspects are also highly modular, making it possible to
  1095. develop plug-and-play implementations of crosscutting
  1096. functionality.
  1097. </para>
  1098. <para>
  1099. AspectJ provides more functionality than was covered by this short
  1100. introduction. The next chapter, <xref linkend="language"/>,
  1101. covers in detail more of the features of the AspectJ language. The
  1102. following chapter, <xref linkend="examples"/>, then presents some
  1103. carefully chosen examples that show you how AspectJ might be used. We
  1104. recommend that you read the next two chapters carefully before
  1105. deciding to adopt AspectJ into a project.
  1106. </para>
  1107. </sect1>
  1108. </chapter>