You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

language.adoc 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  1. [[language]]
  2. = The AspectJ Language
  3. [[language-intro]]
  4. == Introduction
  5. The previous chapter, xref:gettingstarted.adoc#starting[Getting Started with AspectJ], was a brief overview of the
  6. AspectJ language. You should read this chapter to understand AspectJ's
  7. syntax and semantics. It covers the same material as the previous
  8. chapter, but more completely and in much more detail.
  9. We will start out by looking at an example aspect that we'll build out
  10. of a pointcut, an introduction, and two pieces of advice. This example
  11. aspect will gives us something concrete to talk about.
  12. [[language-anatomy]]
  13. == The Anatomy of an Aspect
  14. This lesson explains the parts of AspectJ's aspects. By reading this
  15. lesson you will have an overview of what's in an aspect and you will be
  16. exposed to the new terminology introduced by AspectJ.
  17. === An Example Aspect
  18. Here's an example of an aspect definition in AspectJ:
  19. [source, java]
  20. ....
  21. /*01*/ aspect FaultHandler {
  22. /*02*/
  23. /*03*/ private boolean Server.disabled = false;
  24. /*04*/
  25. /*05*/ private void reportFault() {
  26. /*06*/ System.out.println("Failure! Please fix it.");
  27. /*07*/ }
  28. /*08*/
  29. /*09*/ public static void fixServer(Server s) {
  30. /*10*/ s.disabled = false;
  31. /*11*/ }
  32. /*12*/
  33. /*13*/ pointcut services(Server s): target(s) && call(public * *(..));
  34. /*14*/
  35. /*15*/ before(Server s): services(s) {
  36. /*16*/ if (s.disabled) throw new DisabledException();
  37. /*17*/ }
  38. /*18*/
  39. /*19*/ after(Server s) throwing (FaultException e): services(s) {
  40. /*20*/ s.disabled = true;
  41. /*21*/ reportFault();
  42. /*22*/ }
  43. /*23*/ }
  44. ....
  45. The `FaultHandler` consists of one inter-type field on `Server` (line
  46. 03), two methods (lines 05-07 and 09-11), one pointcut definition (line
  47. 13), and two pieces of advice (lines 15-17 and 19-22).
  48. This covers the basics of what aspects can contain. In general, aspects
  49. consist of an association of other program entities, ordinary variables
  50. and methods, pointcut definitions, inter-type declarations, and advice,
  51. where advice may be before, after or around advice. The remainder of
  52. this lesson focuses on those crosscut-related constructs.
  53. === Pointcuts
  54. AspectJ's pointcut definitions give names to pointcuts. Pointcuts
  55. themselves pick out join points, i.e. interesting points in the
  56. execution of a program. These join points can be method or constructor
  57. invocations and executions, the handling of exceptions, field
  58. assignments and accesses, etc. Take, for example, the pointcut
  59. definition in line 13:
  60. [source, java]
  61. ....
  62. pointcut services(Server s): target(s) && call(public * *(..))
  63. ....
  64. This pointcut, named `services`, picks out those points in the execution
  65. of the program when `Server` objects have their public methods called.
  66. It also allows anyone using the `services` pointcut to access the
  67. `Server` object whose method is being called.
  68. The idea behind this pointcut in the `FaultHandler` aspect is that
  69. fault-handling-related behavior must be triggered on the calls to public
  70. methods. For example, the server may be unable to proceed with the
  71. request because of some fault. The calls of those methods are,
  72. therefore, interesting events for this aspect, in the sense that certain
  73. fault-related things will happen when these events occur.
  74. Part of the context in which the events occur is exposed by the formal
  75. parameters of the pointcut. In this case, that consists of objects of
  76. type `Server`. That formal parameter is then being used on the right
  77. hand side of the declaration in order to identify which events the
  78. pointcut refers to. In this case, a pointcut picking out join points
  79. where a Server is the target of some operation (target(s)) is being
  80. composed (`&&`, meaning and) with a pointcut picking out call join
  81. points (`call(..)`). The calls are identified by signatures that can
  82. include wild cards. In this case, there are wild cards in the return
  83. type position (first `\*`), in the name position (second `*`) and in the
  84. argument list position `(..)`; the only concrete information is given by
  85. the qualifier `public`.
  86. Pointcuts pick out arbitrarily large numbers of join points of a
  87. program. But they pick out only a small number of _kinds_ of join
  88. points. Those kinds of join points correspond to some of the most
  89. important concepts in Java. Here is an incomplete list: method call,
  90. method execution, exception handling, instantiation, constructor
  91. execution, and field access. Each kind of join point can be picked out
  92. by its own specialized pointcut that you will learn about in other parts
  93. of this guide.
  94. === Advice
  95. A piece of advice brings together a pointcut and a body of code to
  96. define aspect implementation that runs at join points picked out by the
  97. pointcut. For example, the advice in lines 15-17 specifies that the
  98. following piece of code
  99. [source, java]
  100. ....
  101. {
  102. if (s.disabled) throw new DisabledException();
  103. }
  104. ....
  105. is executed when instances of the `Server` class have their public
  106. methods called, as specified by the pointcut `services`. More
  107. specifically, it runs when those calls are made, just before the
  108. corresponding methods are executed.
  109. The advice in lines 19-22 defines another piece of implementation that
  110. is executed on the same pointcut:
  111. [source, java]
  112. ....
  113. {
  114. s.disabled = true;
  115. reportFault();
  116. }
  117. ....
  118. But this second method executes after those operations throw exception
  119. of type `FaultException`.
  120. There are two other variations of after advice: upon successful return
  121. and upon return, either successful or with an exception. There is also a
  122. third kind of advice called around. You will see those in other parts of
  123. this guide.
  124. [[language-joinPoints]]
  125. == Join Points and Pointcuts
  126. Consider the following Java class:
  127. [source, java]
  128. ....
  129. class Point {
  130. private int x, y;
  131. Point(int x, int y) { this.x = x; this.y = y; }
  132. void setX(int x) { this.x = x; }
  133. void setY(int y) { this.y = y; }
  134. int getX() { return x; }
  135. int getY() { return y; }
  136. }
  137. ....
  138. In order to get an intuitive understanding of AspectJ's join points and
  139. pointcuts, let's go back to some of the basic principles of Java.
  140. Consider the following a method declaration in class Point:
  141. [source, java]
  142. ....
  143. void setX(int x) { this.x = x; }
  144. ....
  145. This piece of program says that when method named `setX` with an `int`
  146. argument called on an object of type `Point`, then the method body
  147. `{ this.x = x; }` is executed. Similarly, the constructor of the class
  148. states that when an object of type `Point` is instantiated through a
  149. constructor with two `int` arguments, then the constructor body
  150. `{ this.x = x; this.y = y; }` is executed.
  151. One pattern that emerges from these descriptions is
  152. ____
  153. When something happens, then something gets executed.
  154. ____
  155. In object-oriented programs, there are several kinds of "things that
  156. happen" that are determined by the language. We call these the join
  157. points of Java. Join points consist of things like method calls, method
  158. executions, object instantiations, constructor executions, field
  159. references and handler executions. (See the xref:quickreference.adoc#quick[AspectJ Quick Reference] for a
  160. complete listing.)
  161. Pointcuts pick out these join points. For example, the pointcut
  162. [source, java]
  163. ....
  164. pointcut setter():
  165. target(Point) &&
  166. (call(void setX(int)) || call(void setY(int)));
  167. ....
  168. picks out each call to `setX(int)` or `setY(int)` when called on an
  169. instance of `Point`. Here's another example:
  170. [source, java]
  171. ....
  172. pointcut ioHandler(): within(MyClass) && handler(IOException);
  173. ....
  174. This pointcut picks out each the join point when exceptions of type
  175. `IOException` are handled inside the code defined by class `MyClass`.
  176. Pointcut definitions consist of a left-hand side and a right-hand side,
  177. separated by a colon. The left-hand side consists of the pointcut name
  178. and the pointcut parameters (i.e. the data available when the events
  179. happen). The right-hand side consists of the pointcut itself.
  180. === Some Example Pointcuts
  181. Here are examples of pointcuts picking out
  182. when a particular method body executes::
  183. `execution(void Point.setX(int))`
  184. when a method is called::
  185. `call(void Point.setX(int))`
  186. when an exception handler executes::
  187. `handler(ArrayOutOfBoundsException)`
  188. when the object currently executing (i.e. `this`) is of type
  189. `SomeType`::
  190. `this(SomeType)`
  191. when the target object is of type `SomeType`::
  192. `target(SomeType)`
  193. when the executing code belongs to class `MyClass`::
  194. `within(MyClass)`
  195. when the join point is in the control flow of a call to a ``Test``'s
  196. no-argument `main` method::
  197. `cflow(call(void Test.main()))`
  198. Pointcuts compose through the operations `OR` (`||`), `ANT` (`&&`)
  199. and `NOT` (`!`).
  200. * It is possible to use wildcards. So
  201. [arabic]
  202. . `execution(* *(..))`
  203. . `call(* set(..))`
  204. +
  205. means (1) the execution of any method regardless of return or parameter
  206. types, and (2) the call to any method named `set` regardless of return
  207. or parameter types -- in case of overloading there may be more than one
  208. such `set` method; this pointcut picks out calls to all of them.
  209. * You can select elements based on types. For example,
  210. [arabic]
  211. . `execution(int *())`
  212. . `call(* setY(long))`
  213. . `call(* Point.setY(int))`
  214. . `call(*.new(int, int))`
  215. +
  216. means (1) the execution of any method with no parameters that returns an
  217. `int`, (2) the call to any `setY` method that takes a `long` as an
  218. argument, regardless of return type or declaring type, (3) the call to
  219. any of ``Point``'s `setY` methods that take an `int` as an argument,
  220. regardless of return type, and (4) the call to any classes' constructor,
  221. so long as it takes exactly two ``int``s as arguments.
  222. * You can compose pointcuts. For example,
  223. [arabic]
  224. . `target(Point) && call(int *())`
  225. . `call(* *(..)) && (within(Line) || within(Point))`
  226. . `within(*) && execution(*.new(int))`
  227. . `!this(Point) && call(int *(..))`
  228. +
  229. means (1) any call to an `int` method with no arguments on an instance
  230. of `Point`, regardless of its name, (2) any call to any method where the
  231. call is made from the code in ``Point``'s or ``Line``'s type declaration,
  232. (3) the execution of any constructor taking exactly one `int` argument,
  233. regardless of where the call is made from, and (4) any method call to an
  234. `int` method when the executing object is any type except `Point`.
  235. * You can select methods and constructors based on their modifiers and
  236. on negations of modifiers. For example, you can say:
  237. [arabic]
  238. . `call(public * *(..))`
  239. . `execution(!static * *(..))`
  240. . `execution(public !static * *(..))`
  241. +
  242. which means (1) any call to a public method, (2) any execution of a
  243. non-static method, and (3) any execution of a public, non-static method.
  244. * Pointcuts can also deal with interfaces. For example, given the
  245. interface
  246. +
  247. [source, java]
  248. ....
  249. interface MyInterface { ... }
  250. ....
  251. +
  252. the pointcut `call(* MyInterface.*(..))` picks out any call to a method
  253. in ``MyInterface``'s signature -- that is, any method defined by
  254. `MyInterface` or inherited by one of its a supertypes.
  255. [[call-vs-execution]]
  256. === call vs. execution
  257. When methods and constructors run, there are two interesting times
  258. associated with them. That is when they are called, and when they
  259. actually execute.
  260. AspectJ exposes these times as call and execution join points,
  261. respectively, and allows them to be picked out specifically by `call`
  262. and `execution` pointcuts.
  263. So what's the difference between these join points? Well, there are a
  264. number of differences:
  265. Firstly, the lexical pointcut declarations `within` and `withincode`
  266. match differently. At a call join point, the enclosing code is that of
  267. the call site. This means that `call(void m()) && withincode(void m())`
  268. will only capture directly recursive
  269. calls, for example. At an execution join point, however, the program is
  270. already executing the method, so the enclosing code is the method
  271. itself: `execution(void m()) && withincode(void m())` is the same as
  272. `execution(void m())`.
  273. Secondly, the call join point does not capture super calls to non-static
  274. methods. This is because such super calls are different in Java, since
  275. they don't behave via dynamic dispatch like other calls to non-static
  276. methods.
  277. The rule of thumb is that if you want to pick a join point that runs
  278. when an actual piece of code runs (as is often the case for tracing),
  279. use `execution`, but if you want to pick one that runs when a particular
  280. _signature_ is called (as is often the case for production aspects), use
  281. `call`.
  282. === Pointcut composition
  283. Pointcuts are put together with the operators and (spelled `&&`), or
  284. (spelled `||`), and not (spelled `!`). This allows the creation of very
  285. powerful pointcuts from the simple building blocks of primitive
  286. pointcuts. This composition can be somewhat confusing when used with
  287. primitive pointcuts like `cflow` and `cflowbelow`. Here's an example:
  288. `cflow(P)` picks out each join point in the control flow of the join
  289. points picked out by `P`. So, pictorially:
  290. [source, text]
  291. ....
  292. P ---------------------
  293. \
  294. \ cflow of P
  295. \
  296. ....
  297. What does `cflow(P) && cflow(Q)` pick out? Well, it picks out each join point that is
  298. in both the control flow of `P` and in the control flow of `Q`. So...
  299. [source, text]
  300. ....
  301. P ---------------------
  302. \
  303. \ cflow of P
  304. \
  305. \
  306. \
  307. Q -------------\-------
  308. \ \
  309. \ cflow of Q \ cflow(P) && cflow(Q)
  310. \ \
  311. ....
  312. Note that `P` and `Q` might not have any join points in common... but
  313. their control flows might have join points in common.
  314. But what does `cflow(P && Q)` mean? Well, it means the control flow of those join
  315. points that are both picked out by `P` and picked out by `Q`.
  316. [source, text]
  317. ....
  318. P && Q -------------------
  319. \
  320. \ cflow of (P && Q)
  321. \
  322. ....
  323. and if there are _no_ join points that are both picked by `P` and picked
  324. out by `Q`, then there's no chance that there are any join points in the
  325. control flow of `(P && Q)`.
  326. Here's some code that expresses this.
  327. [source, java]
  328. ....
  329. public class Test {
  330. public static void main(String[] args) {
  331. foo();
  332. }
  333. static void foo() {
  334. goo();
  335. }
  336. static void goo() {
  337. System.out.println("hi");
  338. }
  339. }
  340. aspect A {
  341. pointcut fooPC(): execution(void Test.foo());
  342. pointcut gooPC(): execution(void Test.goo());
  343. pointcut printPC(): call(void java.io.PrintStream.println(String));
  344. before(): cflow(fooPC()) && cflow(gooPC()) && printPC() && !within(A) {
  345. System.out.println("should occur");
  346. }
  347. before(): cflow(fooPC() && gooPC()) && printPC() && !within(A) {
  348. System.out.println("should not occur");
  349. }
  350. }
  351. ....
  352. The `!within(A)` pointcut above is required to avoid the `printPC`
  353. pointcut applying to the `System.out.println` call in the advice body.
  354. If this was not present a recursive call would result as the pointcut
  355. would apply to its own advice. (See xref:pitfalls.adoc#pitfalls-infiniteLoops[Infinite loops]
  356. for more details.)
  357. === Pointcut Parameters
  358. Consider again the first pointcut definition in this chapter:
  359. [source, java]
  360. ....
  361. pointcut setter():
  362. target(Point) &&
  363. (call(void setX(int)) || call(void setY(int)));
  364. ....
  365. As we've seen, this pointcut picks out each call to `setX(int)` or
  366. `setY(int)` methods where the target is an instance of `Point`. The
  367. pointcut is given the name `setter` and no parameters on the left-hand
  368. side. An empty parameter list means that none of the context from the
  369. join points is published from this pointcut. But consider another
  370. version of version of this pointcut definition:
  371. [source, java]
  372. ....
  373. pointcut setter(Point p):
  374. target(p) &&
  375. (call(void setX(int)) || call(void setY(int)));
  376. ....
  377. This version picks out exactly the same join points. But in this
  378. version, the pointcut has one parameter of type `Point`. This means that
  379. any advice that uses this pointcut has access to a `Point` from each
  380. join point picked out by the pointcut. Inside the pointcut definition
  381. this `Point` is named `p` is available, and according to the right-hand
  382. side of the definition, that `Point p` comes from the `target` of each
  383. matched join point.
  384. Here's another example that illustrates the flexible mechanism for
  385. defining pointcut parameters:
  386. [source, java]
  387. ....
  388. pointcut testEquality(Point p):
  389. target(Point) &&
  390. args(p) &&
  391. call(boolean equals(Object));
  392. ....
  393. This pointcut also has a parameter of type `Point`. Similar to the
  394. `setter` pointcut, this means that anyone using this pointcut has
  395. access to a `Point` from each join point. But in this case, looking at
  396. the right-hand side we find that the object named in the parameters is
  397. not the target `Point` object that receives the call; it's the argument
  398. (also of type `Point`) passed to the `equals` method when some other
  399. `Point` is the target. If we wanted access to both ``Point``s, then the
  400. pointcut definition that would expose target `Point p1` and argument
  401. `Point p2` would be
  402. [source, java]
  403. ....
  404. pointcut testEquality(Point p1, Point p2):
  405. target(p1) &&
  406. args(p2) &&
  407. call(boolean equals(Object));
  408. ....
  409. Let's look at another variation of the `setter` pointcut:
  410. [source, java]
  411. ....
  412. pointcut setter(Point p, int newval):
  413. target(p) &&
  414. args(newval) &&
  415. (call(void setX(int)) || call(void setY(int)));
  416. ....
  417. In this case, a `Point` object and an `int` value are exposed by the
  418. named pointcut. Looking at the the right-hand side of the definition, we
  419. find that the `Point` object is the target object, and the `int` value
  420. is the called method's argument.
  421. The use of pointcut parameters is relatively flexible. The most
  422. important rule is that all the pointcut parameters must be bound at
  423. every join point picked out by the pointcut. So, for example, the
  424. following pointcut definition will result in a compilation error:
  425. [source, java]
  426. ....
  427. pointcut badPointcut(Point p1, Point p2):
  428. (target(p1) && call(void setX(int))) ||
  429. (target(p2) && call(void setY(int)));
  430. ....
  431. because `p1` is only bound when calling `setX`, and `p2` is only bound
  432. when calling `setY`, but the pointcut picks out all of these join points
  433. and tries to bind both `p1` and `p2`.
  434. [[example]]
  435. === Example: `HandleLiveness`
  436. The example below consists of two object classes (plus an exception
  437. class) and one aspect. Handle objects delegate their public, non-static
  438. operations to their `Partner` objects. The aspect `HandleLiveness`
  439. ensures that, before the delegations, the partner exists and is alive,
  440. or else it throws an exception.
  441. [source, java]
  442. ....
  443. class Handle {
  444. Partner partner = new Partner();
  445. public void foo() { partner.foo(); }
  446. public void bar(int x) { partner.bar(x); }
  447. public static void main(String[] args) {
  448. Handle h1 = new Handle();
  449. h1.foo();
  450. h1.bar(2);
  451. }
  452. }
  453. class Partner {
  454. boolean isAlive() { return true; }
  455. void foo() { System.out.println("foo"); }
  456. void bar(int x) { System.out.println("bar " + x); }
  457. }
  458. aspect HandleLiveness {
  459. before(Handle handle): target(handle) && call(public * *(..)) {
  460. if ( handle.partner == null || !handle.partner.isAlive() ) {
  461. throw new DeadPartnerException();
  462. }
  463. }
  464. }
  465. class DeadPartnerException extends RuntimeException {}
  466. ....
  467. [[pointcut-best-practice]]
  468. === Writing good pointcuts
  469. During compilation, AspectJ processes pointcuts in order to try and
  470. optimize matching performance. Examining code and determining if each
  471. join point matches (statically or dynamically) a given pointcut is a
  472. costly process. (A dynamic match means the match cannot be fully
  473. determined from static analysis and a test will be placed in the code to
  474. determine if there is an actual match when the code is running). On
  475. first encountering a pointcut declaration, AspectJ will rewrite it into
  476. an optimal form for the matching process. What does this mean? Basically
  477. pointcuts are rewritten in DNF (Disjunctive Normal Form) and the
  478. components of the pointcut are sorted such that those components that
  479. are cheaper to evaluate are checked first. This means users do not have
  480. to worry about understanding the performance of various pointcut
  481. designators and may supply them in any order in their pointcut
  482. declarations.
  483. However, AspectJ can only work with what it is told, and for optimal
  484. performance of matching the user should think about what they are trying
  485. to achieve and narrow the search space for matches as much as they can
  486. in the definition. Basically there are three kinds of pointcut
  487. designator: kinded, scoping and context:
  488. * Kinded designators are those which select a particular kind of join
  489. point. For example: `execution, get, set, call, handler`
  490. * Scoping designators are those which select a group of join points of
  491. interest (of probably many kinds). For example: `within, withincode`
  492. * Contextual designators are those that match (and optionally bind)
  493. based on context. For example: `this, target, @annotation`
  494. A well written pointcut should try and include at least the first two
  495. types (kinded and scoping), whilst the contextual designators may be
  496. included if wishing to match based on join point context, or bind that
  497. context for use in the advice. Supplying either just a kinded designator
  498. or just a contextual designator will work but could affect weaving
  499. performance (time and memory used) due to all the extra processing and
  500. analysis. Scoping designators are very fast to match, they can very
  501. quickly dismiss groups of join points that should not be further
  502. processed - that is why a good pointcut should always include one if
  503. possible.
  504. [[language-advice]]
  505. == Advice
  506. Advice defines pieces of aspect implementation that execute at
  507. well-defined points in the execution of the program. Those points can be
  508. given either by named pointcuts (like the ones you've seen above) or by
  509. anonymous pointcuts. Here is an example of an advice on a named
  510. pointcut:
  511. [source, java]
  512. ....
  513. pointcut setter(Point p1, int newval):
  514. target(p1) && args(newval)
  515. (call(void setX(int) || call(void setY(int)));
  516. before(Point p1, int newval): setter(p1, newval) {
  517. System.out.println(
  518. "About to set something in " + p1 +
  519. " to the new value " + newval
  520. );
  521. }
  522. ....
  523. And here is exactly the same example, but using an anonymous pointcut:
  524. [source, java]
  525. ....
  526. before(Point p1, int newval):
  527. target(p1) && args(newval)
  528. (call(void setX(int)) || call(void setY(int)))
  529. {
  530. System.out.println(
  531. "About to set something in " + p1 +
  532. " to the new value " + newval
  533. );
  534. }
  535. ....
  536. Here are examples of the different advice:
  537. This before advice runs just before the join points picked out by the
  538. (anonymous) pointcut:
  539. [source, java]
  540. ....
  541. before(Point p, int x): target(p) && args(x) && call(void setX(int)) {
  542. if (!p.assertX(x)) return;
  543. }
  544. ....
  545. This after advice runs just after each join point picked out by the
  546. (anonymous) pointcut, regardless of whether it returns normally or
  547. throws an exception:
  548. [source, java]
  549. ....
  550. after(Point p, int x):
  551. target(p) && args(x) && call(void setX(int))
  552. {
  553. if (!p.assertX(x)) throw new PostConditionViolation();
  554. }
  555. ....
  556. This after returning advice runs just after each join point picked out
  557. by the (anonymous) pointcut, but only if it returns normally. The return
  558. value can be accessed, and is named `x` here. After the advice runs, the
  559. return value is returned:
  560. [source, java]
  561. ....
  562. after(Point p) returning(int x):
  563. target(p) && call(int getX())
  564. {
  565. System.out.println("Returning int value " + x + " for p = " + p);
  566. }
  567. ....
  568. This after throwing advice runs just after each join point picked out by
  569. the (anonymous) pointcut, but only when it throws an exception of type
  570. `Exception`. Here the exception value can be accessed with the name `e`.
  571. The advice re-raises the exception after it's done:
  572. [source, java]
  573. ....
  574. after() throwing(Exception e):
  575. target(Point) && call(void setX(int))
  576. {
  577. System.out.println(e);
  578. }
  579. ....
  580. This around advice traps the execution of the join point; it runs
  581. _instead_ of the join point. The original action associated with the
  582. join point can be invoked through the special `proceed` call:
  583. [source, java]
  584. ....
  585. void around(Point p, int x):
  586. target(p)
  587. && args(x)
  588. && call(void setX(int))
  589. {
  590. if (p.assertX(x)) proceed(p, x);
  591. p.releaseResources();
  592. }
  593. ....
  594. [[language-interType]]
  595. == Inter-type declarations
  596. Aspects can declare members (fields, methods, and constructors) that are
  597. owned by other types. These are called inter-type members. Aspects can
  598. also declare that other types implement new interfaces or extend a new
  599. class. Here are examples of some such inter-type declarations:
  600. This declares that each `Server` has a `boolean` field named `disabled`,
  601. initialized to `false`:
  602. [source, java]
  603. ....
  604. private boolean Server.disabled = false;
  605. ....
  606. It is declared `private`, which means that it is private _to the
  607. aspect_: only code in the aspect can see the field. And even if `Server`
  608. has another private field named `disabled` (declared in `Server` or in
  609. another aspect) there won't be a name collision, since no reference to
  610. `disabled` will be ambiguous.
  611. This declares that each `Point` has an `int` method named `getX` with no
  612. arguments that returns whatever `this.x` is:
  613. [source, java]
  614. ....
  615. public int Point.getX() { return this.x; }
  616. ....
  617. Inside the body, `this` is the `Point` object currently executing.
  618. Because the method is publically declared any code can call it, but if
  619. there is some other `Point.getX()` declared there will be a compile-time
  620. conflict.
  621. This publically declares a two-argument constructor for `Point`:
  622. [source, java]
  623. ....
  624. public Point.new(int x, int y) { this.x = x; this.y = y; }
  625. ....
  626. This publicly declares that each `Point` has an `int` field named `x`,
  627. initialized to zero:
  628. [source, java]
  629. ....
  630. public int Point.x = 0;
  631. ....
  632. Because this is publically declared, it is an error if `Point` already
  633. has a field named `x` (defined by `Point` or by another aspect).
  634. This declares that the `Point` class implements the `Comparable`
  635. interface:
  636. [source, java]
  637. ....
  638. declare parents: Point implements Comparable;
  639. ....
  640. Of course, this will be an error unless `Point` defines the methods
  641. required by `Comparable`.
  642. This declares that the `Point` class extends the `GeometricObject`
  643. class.
  644. [source, java]
  645. ....
  646. declare parents: Point extends GeometricObject;
  647. ....
  648. An aspect can have several inter-type declarations. For example, the
  649. following declarations
  650. [source, java]
  651. ....
  652. public String Point.name;
  653. public void Point.setName(String name) { this.name = name; }
  654. ....
  655. publicly declare that Point has both a String field `name` and a `void`
  656. method `setName(String)` (which refers to the `name` field declared by
  657. the aspect).
  658. An inter-type member can only have one target type, but often you may
  659. wish to declare the same member on more than one type. This can be done
  660. by using an inter-type member in combination with a private interface:
  661. [source, java]
  662. ....
  663. aspect A {
  664. private interface HasName {}
  665. declare parents: (Point || Line || Square) implements HasName;
  666. private String HasName.name;
  667. public String HasName.getName() { return name; }
  668. }
  669. ....
  670. This declares a marker interface `HasName`, and also declares that any
  671. type that is either `Point`, `Line`, or `Square` implements that
  672. interface. It also privately declares that all `HasName` object have a
  673. `String` field called `name`, and publically declares that all `HasName`
  674. objects have a `String` method `getName()` (which refers to the
  675. privately declared `name` field).
  676. As you can see from the above example, an aspect can declare that
  677. interfaces have fields and methods, even non-constant fields and methods
  678. with bodies.
  679. === Inter-type Scope
  680. AspectJ allows private and package-protected (default) inter-type
  681. declarations in addition to public inter-type declarations. Private
  682. means private in relation to the aspect, not necessarily the target
  683. type. So, if an aspect makes a private inter-type declaration of a field
  684. [source, java]
  685. ....
  686. private int Foo.x;
  687. ....
  688. Then code in the aspect can refer to ``Foo``'s `x` field, but nobody else
  689. can. Similarly, if an aspect makes a package-protected introduction,
  690. [source, java]
  691. ....
  692. int Foo.x;
  693. ....
  694. then everything in the aspect's package (which may or may not be ``Foo``'s
  695. package) can access `x`.
  696. === Example: `PointAssertions`
  697. The example below consists of one class and one aspect. The aspect
  698. privately declares the assertion methods of `Point`, `assertX` and
  699. `assertY`. It also guards calls to `setX` and `setY` with calls to these
  700. assertion methods. The assertion methods are declared privately because
  701. other parts of the program (including the code in `Point`) have no
  702. business accessing the assert methods. Only the code inside of the
  703. aspect can call those methods.
  704. [source, java]
  705. ....
  706. class Point {
  707. int x, y;
  708. public void setX(int x) { this.x = x; }
  709. public void setY(int y) { this.y = y; }
  710. public static void main(String[] args) {
  711. Point p = new Point();
  712. p.setX(3); p.setY(333);
  713. }
  714. }
  715. aspect PointAssertions {
  716. private boolean Point.assertX(int x) {
  717. return (x <= 100 && x >= 0);
  718. }
  719. private boolean Point.assertY(int y) {
  720. return (y <= 100 && y >= 0);
  721. }
  722. before(Point p, int x): target(p) && args(x) && call(void setX(int)) {
  723. if (!p.assertX(x))
  724. System.out.println("Illegal value for x"); return;
  725. }
  726. before(Point p, int y): target(p) && args(y) && call(void setY(int)) {
  727. if (!p.assertY(y))
  728. System.out.println("Illegal value for y"); return;
  729. }
  730. }
  731. ....
  732. [[language-thisJoinPoint]]
  733. == `thisJoinPoint`
  734. AspectJ provides a special reference variable, `thisJoinPoint`, that
  735. contains reflective information about the current join point for the
  736. advice to use. The `thisJoinPoint` variable can only be used in the
  737. context of advice, just like `this` can only be used in the context of
  738. non-static methods and variable initializers. In advice, `thisJoinPoint`
  739. is an object of type
  740. xref:../runtime-api/org/aspectj/lang/JoinPoint.html[`org.aspectj.lang.JoinPoint`].
  741. One way to use it is simply to print it out. Like all Java objects,
  742. `thisJoinPoint` has a `toString()` method that makes quick-and-dirty
  743. tracing easy:
  744. [source, java]
  745. ....
  746. aspect TraceNonStaticMethods {
  747. before(Point p): target(p) && call(* *(..)) {
  748. System.out.println("Entering " + thisJoinPoint + " in " + p);
  749. }
  750. }
  751. ....
  752. The type of `thisJoinPoint` includes a rich reflective class hierarchy
  753. of signatures, and can be used to access both static and dynamic
  754. information about join points such as the arguments of the join point:
  755. [source, java]
  756. ....
  757. thisJoinPoint.getArgs()
  758. ....
  759. In addition, it holds an object consisting of all the static information
  760. about the join point such as corresponding line number and static
  761. signature:
  762. [source, java]
  763. ....
  764. thisJoinPoint.getStaticPart()
  765. ....
  766. If you only need the static information about the join point, you may
  767. access the static part of the join point directly with the special
  768. variable `thisJoinPointStaticPart`. Using `thisJoinPointStaticPart` will
  769. avoid the run-time creation of the join point object that may be
  770. necessary when using `thisJoinPoint` directly.
  771. It is always the case that
  772. [source, java]
  773. ....
  774. thisJoinPointStaticPart == thisJoinPoint.getStaticPart()
  775. thisJoinPoint.getKind() == thisJoinPointStaticPart.getKind()
  776. thisJoinPoint.getSignature() == thisJoinPointStaticPart.getSignature()
  777. thisJoinPoint.getSourceLocation() == thisJoinPointStaticPart.getSourceLocation()
  778. ....
  779. One more reflective variable is available:
  780. `thisEnclosingJoinPointStaticPart`. This, like
  781. `thisJoinPointStaticPart`, only holds the static part of a join point,
  782. but it is not the current but the enclosing join point. So, for example,
  783. it is possible to print out the calling source location (if available)
  784. with
  785. [source, java]
  786. ....
  787. before() : execution (* *(..)) {
  788. System.err.println(thisEnclosingJoinPointStaticPart.getSourceLocation())
  789. }
  790. ....