cseweb.ucsd.edu · The AspectJ Language Semantics of Advice (dynamic) Open Classes (static) ...

12
1 Macneil Shonle [email protected] class Foo { static int x = 20; void bar() { int x = 10; print_x(); } void print_x() { System.out.print(x); } } What value will “print_x” print using lexical scope? Dynamic scope? print_x record Lexical scope looks up the syntax tree at compile time Dynamic scope looks up the dynamic call stack at runtime class Foo field x method bar method print_x bar record main record args; foo ptr x statement list statement list class Foo { void bar() { final int x = 20; callIt(new Runnable() { public void run() { System.out.println(x); x is a free variable } }); } void callIt(Runnable runnable) { int x = 10; runnable.run(); } }

Transcript of cseweb.ucsd.edu · The AspectJ Language Semantics of Advice (dynamic) Open Classes (static) ...

Page 1: cseweb.ucsd.edu · The AspectJ Language Semantics of Advice (dynamic) Open Classes (static) ...

1

������� �

�������� ������ �� �����

Macneil [email protected]

���������� ����������������

class Foo {static int x = 20;void bar() {

int x = 10;print_x();

}void print_x() {

System.out.print(x);}

}

What value will “print_x”print using lexical scope?

Dynamic scope?

print_x record

������������������

� Lexical scope looks up the syntax tree at compile time

� Dynamic scope looks up the dynamic call stack at runtime

class Foo

field x

method bar

method print_x

bar record

main record args; foo ptr

x

statement list

statement list

������������ ��������class Foo {

void bar() {final int x = 20;callIt(new Runnable() {

public void run() {System.out.println(x); �x is a free variable

}});

}void callIt(Runnable runnable) {

int x = 10;runnable.run();

}}

Page 2: cseweb.ucsd.edu · The AspectJ Language Semantics of Advice (dynamic) Open Classes (static) ...

2

��������������� �� ��������������

������

� Each scoping rule seems like it might be more useful than the other for special cases.

� Why would some people believe that lexical scope is better in the general case? ...

��������������� �� ��������������

�������!������"

� Lexical scope allows for better Separation of Concerns; fewer strange bugs would occur

� Strongly supporting SOC drives PL design

“Dynamic scoping is generally considered to have been a big mistake, and was fixed in recent versions of Lisp, such as Common Lisp, which were influenced by Scheme.”

– Paul Wilson, UT Austin

��� ����

� Separation of Concerns in O-O PLs� Limits of O-O Modularization� Aspects: Advanced Modularization

� Terminology

� The AspectJ Language� Semantics of Advice (dynamic)� Open Classes (static)

���� �������� ��� �������

� Selection concerns are handled quite nicely in OOP languages with polymorphism

Selectingi f ( w. get Type( ) == A)

dr awA( ( A) w) ;

el se i f ( w. get Type( ) == B)

dr awB( ( B) w) ;

el se i f ( w. get Type( ) == C)

dr awC( ( C) w) ;

. . .

Polymorphismw. dr aw( ) ;

Vs.

Page 3: cseweb.ucsd.edu · The AspectJ Language Semantics of Advice (dynamic) Open Classes (static) ...

3

���� �������� ��� �������

� Usually, when SOC is achieved in a PL, we say that the concern is modularized

� Exception handling is another good example of separation of concerns: it creates another channel for error-specific information to flow:

Data-flow/Control-flow

Error-flow/Error-control

method calls, control anditeration constructs

catch blocks, throw

#���� �$����

Nicely separated concerns:

� XML Parsing� Pattern matching� Collections� Numerical processing

Language features allow for very nice separation

����������#���� �$����

Some concerns crosscut modular boundaries:

� Caching� Object marshalling� Logging� Thread synchronization

�������������� �

� A concern crosscuts when it appears in several different modules

� Two flavors of crosscutting concerns:� A concern is tangled if it is mixed with code that

addresses a separate concern� A concern is scattered if it appears in several

different modules.

Page 4: cseweb.ucsd.edu · The AspectJ Language Semantics of Advice (dynamic) Open Classes (static) ...

4

%�������������� ��

� In the C-style of error handling, functions returned error codes that needed to be checked

� As a result, error handling (identification of errors; accessing data that describes the error; and changing control-flow) was both tangled and scattered:� Functions unrelated to error handling had to check

and “pass up” errors it found

%���&��������������� �����

� �� �����

� Write concerns in local aspects, and have them woven globally into the program by a weaver

weaver

%���������

� An aspect is a special kind of module that specifically addresses crosscutting concerns

� Aspects are needed when the constructs available in a traditional programming language cannot encapsulate the crosscutting concern

� The aspect can be woven in either at compile-time, class load-time, run-time, or a mix of these.

�'���(� �����������������

! ���������'�)**+"

� Red text are synchronization concerns

� Green text are Remote Method Invocation concerns

� In this Java program, the concerns are tangled

public class Shape implements ShapeI {

protected Adj ust abl eLocat i on l oc ; protected Adj ust abl eDi mens i on di m;public Shape( ) {

l oc = new Adj us t abl eLocat i on( 0, 0) ;di m = new Adj us t abl eDi mens i on( 0, 0) ;

}double get _x ( ) throws RemoteException {

return l oc . x ( ) ; }void set _x ( i nt x ) throws RemoteException {

l oc . set _x( ) ; }double get _y ( ) throws RemoteException {

return l oc . y ( ) ; }void set _y ( i nt y ) throws RemoteException {

l oc . set _y( ) ; }double get _wi dt h( ) throws RemoteException {

return di m. wi dt h( ) ; } void set _wi dt h( i nt w) throws RemoteException {

di m. set _w( ) ; }void adj us t Locat i on( ) throws RemoteException {

l oc . adj ust ( ) ;}void adj us t Di mensi ons( ) throws RemoteException {

di m. adj ust ( ) ;}

}

class Adj us t abl eLocat i on {protected double x_, y_;public Adj us t abl eLocat i on( double x , double y ) {

x_ = x ; y_ = y ; }synchr oni zed double get _x ( ) { return x_; }synchr oni zed void set _x ( i nt x) { x_ = x ; }synchr oni zed double get _y ( ) { return y_; }synchr oni zed void set _y ( i nt y) { y_ = y ; }synchr oni zed void adj ust ( ) {

x_ = l ongCal cul at i on1( ) ; y_ = l ongCal cul at i on2( ) ;

}}class Adj us t abl eDi mens i on {

protected double wi dt h_=0. 0, hei ght _=0. 0;public Adj us t abl eDi mensi on( double h, double w) {

hei ght _ = h; wi dt h_ = w; }synchr oni zed double get _wi dt h( ) { return wi dt h_; }synchr oni zed void set _w( i nt w) { wi dt h_ = w; }synchr oni zed void adj ust ( ) {

wi dt h_ = l ongCal cul at i on3( ) ; hei ght _ = l ongCal cul at i on4( ) ;

}}

interface ShapeI extends Remote {double get _x ( ) throws RemoteException ;void set _x ( i nt x ) throws RemoteException ;double get _y ( ) throws RemoteException ;void set _y ( i nt y ) throws RemoteException ;double get _wi dt h( ) throws RemoteException ;void set _wi dt h( i nt w) throws RemoteException ;void adj us t Locat i on( ) throws RemoteException ;void adj us t Di mensi ons( ) throws RemoteException ;

}

Page 5: cseweb.ucsd.edu · The AspectJ Language Semantics of Advice (dynamic) Open Classes (static) ...

5

public class Shape {protected double x_= 0. 0, y_= 0. 0;protected double wi dt h_=0. 0, hei ght _=0. 0;

double get _x ( ) { return x_( ) ; }void set _x ( i nt x ) { x_ = x ; }double get _y ( ) { return y_( ) ; }void set _y ( i nt y ) { y_ = y ; }double get _wi dt h( ) { return wi dt h_( ) ; } void set _wi dt h( i nt w) { wi dt h_ = w; }void adj us t Locat i on( ) {

x_ = l ongCal cul at i on1( ) ; y_ = l ongCal cul at i on2( ) ;

}void adj us t Di mensi ons( ) {

wi dt h_ = l ongCal cul at i on3( ) ; hei ght _ = l ongCal cul at i on4( ) ;

}}

coordinator Shape {selfex adj us t Locat i on, adj us t Di mens i ons;mutex { adj us t Locat i on, get _x , set _x ,

get _y , set _y } ;mutex { adj us t Di mensi ons, get _wi dt h, set _wi dt h} ;

}

portal Shape {double get _x ( ) { } ;void set _x ( i nt x ) { } ;double get _y ( ) { } ;void set _y ( i nt y ) { } ;double get _wi dt h( ) { } ;void set _wi dt h( i nt w) { } ;void adj us t Locat i on( ) { } ;void adj us t Di mensi ons( ) { } ;

}

�'���(� �����������������

! ���������'�)**+"

Instead of writing this

Write this

Concerns are now separated

public class Shape implements ShapeI {

protected Adj ust abl eLocat i on l oc ; protected Adj ust abl eDi mens i on di m;public Shape( ) {

l oc = new Adj us t abl eLocat i on( 0, 0) ;di m = new Adj us t abl eDi mens i on( 0, 0) ;

}double get _x ( ) throws RemoteException {

return l oc . x ( ) ; }void set _x ( i nt x ) throws RemoteException {

l oc . set _x( ) ; }double get _y ( ) throws RemoteException {

return l oc . y ( ) ; }void set _y ( i nt y ) throws RemoteException {

l oc . set _y( ) ; }double get _wi dt h( ) throws RemoteException {

return di m. wi dt h( ) ; } void set _wi dt h( i nt w) throws RemoteException {

di m. set _w( ) ; }void adj us t Locat i on( ) throws RemoteException {

l oc . adj ust ( ) ;}void adj us t Di mensi ons( ) throws RemoteException {

di m. adj ust ( ) ;}

}

class Adj us t abl eLocat i on {protected double x_, y_;public Adj us t abl eLocat i on( double x , double y ) {

x_ = x ; y_ = y ; }synchr oni zed double get _x ( ) { return x_; }synchr oni zed void set _x ( i nt x) { x_ = x ; }synchr oni zed double get _y ( ) { return y_; }synchr oni zed void set _y ( i nt y) { y_ = y ; }synchr oni zed void adj ust ( ) {

x_ = l ongCal cul at i on1( ) ; y_ = l ongCal cul at i on2( ) ;

}}class Adj us t abl eDi mens i on {

protected double wi dt h_=0. 0, hei ght _=0. 0;public Adj us t abl eDi mensi on( double h, double w) {

hei ght _ = h; wi dt h_ = w; }synchr oni zed double get _wi dt h( ) { return wi dt h_; }synchr oni zed void set _w( i nt w) { wi dt h_ = w; }synchr oni zed void adj ust ( ) {

wi dt h_ = l ongCal cul at i on3( ) ; hei ght _ = l ongCal cul at i on4( ) ;

}}

interface ShapeI extends Remote {double get _x ( ) throws RemoteException ;void set _x ( i nt x ) throws RemoteException ;double get _y ( ) throws RemoteException ;void set _y ( i nt y ) throws RemoteException ;double get _wi dt h( ) throws RemoteException ;void set _wi dt h( i nt w) throws RemoteException ;void adj us t Locat i on( ) throws RemoteException ;void adj us t Di mensi ons( ) throws RemoteException ;

}

, ���������������

� D is a domain-specific aspect language: it only handles synchronization and marshalling concerns

� D was the inspiration of AspectJ� AspectJ is an extension to Java and is a

general purpose aspect language� AspectJ has a very sophisticated weaving

language

������� ,���� ��

� Advice (The Join-Point Model)� Dynamic� Concerned with identifying events that occur when

the program is running, and changing or adding to its behavior

� Open Classes (Intertype Declarations)� Static� Adds additional methods or fields to classes, in a

way that achieves finer-grained access than just public, private, protected.

%������������#���

� A join-point is a dynamic event that occurs when the program is running

� Example events:� A method or constructor is called� A method or constructor is executed� A field get or set operation� An exception handler is entered

Page 6: cseweb.ucsd.edu · The AspectJ Language Semantics of Advice (dynamic) Open Classes (static) ...

6

��������

� A pointcut is a set of join-points� Usual set-theory operations (&&, ||, !)� Special predicates

� Examples:� cal l ( voi d Li ne. set P1( Poi nt ) )

� cal l ( voi d Li ne. set P1( Poi nt ) )| | cal l ( voi d Li ne. set P2( Poi nt ) )

� cal l ( voi d Li ne. set * ( Poi nt ) )

������ A pointcut cut can have extra behavior

attached to it: i.e., when one of the join-points occurs, execute additional code.

� We call this additional code advice.

aspect Di spl ayUpdat i ng {

poi nt cut move( ) : � pointcutcal l ( voi d Li ne. set * ( Poi nt ) ) ;

af t er ( ) r et ur ni ng: move( ) { � adviceDi spl ay. updat e( ) ;

}

}

-�����������

� before� before a join-point occurs, execute the advice

body

� after� after a join-point occurs, execute the advice body

� around� execute the advice body instead of join-point� optionally execute join-point when “proceed” is

called

(������.�/�����0� ������������

aspect Hel l oLoggi ngWor l d {

poi nt cut publ i cMet hods( ) :

execut i on( publ i c * mypackage. . * ( . . ) ) ;Obj ect ar ound( ) : publ i cMet hods( ) {

Syst em. out . pr i nt l n( " Ent er i ng " + t hi sJoi nPoi nt St at i cPar t ) ;

Obj ect o = pr oceed( ) ;

Syst em. out . pr i nt l n( " Leavi ng " +t hi sJoi nPoi nt St at i cPar t

+ " r et ur ni ng " + o) ;

r et ur n o;

}

}

Page 7: cseweb.ucsd.edu · The AspectJ Language Semantics of Advice (dynamic) Open Classes (static) ...

7

,��� ��(������

FigureElement

Line Point

Display

2

(������.�&������ ��������� ������

���� ����� �$���������������aspect Di spl ayUpdat i ng {

poi nt cut move( Fi gur eEl ement f i gEl t ) :t ar get ( f i gEl t ) && ( cal l ( voi d Fi gur eEl ement . moveBy( i nt , i nt ) )

| | cal l ( voi d Li ne. set P1( Poi nt ) )| | cal l ( voi d Li ne. set P2( Poi nt ) )| | cal l ( voi d Poi nt . set X( i nt ) )| | cal l ( voi d Poi nt . set Y( i nt ) ) ) ;

af t er ( Fi gur eEl ement f e) r et ur ni ng: move( f e) {Di spl ay. updat e( f e) ;

}}

�����.�1�� ������� �� ���,���

!�2�2'��������������������3"

� cf l ow( Pointcut)

� all join points in the dynamic control flow of any join point picked out by Pointcut

� basically, if a join point is on the stack, you’re in that join point’s control flow

� cf l owbel ow( Pointcut)

� all join points in the dynamic control flow below any join point picked out by Pointcut

4��������� ��������1�����

�������2����� ����aspect Di spl ayUpdat i ng {

poi nt cut move( Fi gur eEl ement f i gEl t ) :t ar get ( f i gEl t ) && ( cal l ( voi d Fi gur eEl ement . moveBy( i nt , i nt ) )

| | cal l ( voi d Li ne. set P1( Poi nt ) )| | cal l ( voi d Li ne. set P2( Poi nt ) )| | cal l ( voi d Poi nt . set X( i nt ) )| | cal l ( voi d Poi nt . set Y( i nt ) ) ) ;

poi nt cut t opLevel Move( Fi gur eEl ement f e) :move( f e) && ! cf l owbel ow( move( f e) ) ;

af t er ( Fi gur eEl ement f e) r et ur ni ng: t opLevel Move( f e) {Di spl ay. updat e( f e) ;

}}

Page 8: cseweb.ucsd.edu · The AspectJ Language Semantics of Advice (dynamic) Open Classes (static) ...

8

(������.� �����

aspect Poi nt Cachi ng {pr i vat e MyLookupTabl e cache = new MyLookupTabl e( ) ;

Poi nt ar ound( i nt x , i nt y) :cal l ( Poi nt . new( i nt , i nt ) ) && ar gs( x, y ) {

Poi nt r et = cache. l ookup( x , y) ;i f ( r et == nul l ) {

r et = pr oceed( x, y ) ;cache. add( x, y, r et ) ;

}r et ur n r et ;

}}

������������.�%���0� �����������

Workers need to know the caller:• capabilities• charge backs• to customize result

This is very similar to whatdynamic scope provides!

caller1

caller2

Service

worker 1 worker 3worker 2

����������������������

Workers need to know the caller:• capabilities• charge backs• to customize result

caller1

caller2

Service

worker 1 worker 3worker 2

����������������������

pointcut invocations(Caller c):this(c) && call(void Service.doService(String));

Page 9: cseweb.ucsd.edu · The AspectJ Language Semantics of Advice (dynamic) Open Classes (static) ...

9

����������������������

pointcut invocations(Caller c):this(c) && call(void Service.doService(String));

pointcut workPoints(Worker w):target(w) && call(void Worker.doTask(Task));

pointcut invocations(Caller c):this(c) && call(void Service.doService(String));

pointcut workPoints(Worker w):target(w) && call(void Worker.doTask(Task));

pointcut perCallerWork(Caller c, Worker w):cflow(invocations(c)) && workPoints(w);

����������������������

abstract aspect CapabilityChecking {

pointcut invocations(Caller c):this(c) && call(void Service.doService(String));

pointcut workPoints(Worker w):target(w) && call(void Worker.doTask(Task));

pointcut perCallerWork(Caller c, Worker w):cflow(invocations(c)) && workPoints(w);

before (Caller c, Worker w): perCallerWork(c, w) { w.checkCapabilities(c);

}}

���������������������� ������������������!������� ��"

A

B

A “knows about” B

Page 10: cseweb.ucsd.edu · The AspectJ Language Semantics of Advice (dynamic) Open Classes (static) ...

10

�����������������.�% ��3�5)

A

B

Putting in a before or afteradvice changes the “knowsabout” relationship

(This feature is not so flashy:Common Lisp had it first!)

�����������������

A

B

C

DUsually, lots moremodules need toknow about B

Think of each redarrow as a repeated line of code

�����������������

A

B

C

DAdvice can letus change all ofthe arrows (sothat B only needsto know about A,C and D)... but that isn’t much better

�����������������.�% ��3�56

A

B

C

DB can know lessabout the modulesby instead creatinga set based onsome commonproperties

pointcut

Page 11: cseweb.ucsd.edu · The AspectJ Language Semantics of Advice (dynamic) Open Classes (static) ...

11

��� ���������� �����

� Provides for open classes:

aspect Render i ng {publ i c voi d Par t i c l e. dr aw( Gr aphi cs g) { …}

publ i c voi d Wal l . dr aw( Gr aphi cs g) { …}

publ i c voi d Vect or . dr aw( Gr aphi cs g) { …}

}

��� �� ����������

BaseClass

Foo Bar Czar

Suppose Bar and Czar need to have some access todata that belongs to BaseClass, but Foo should beexcluded from touching it

��� �� ����������

BaseClass

Foo Bar Czar

Suppose Bar and Czar need to have some access todata that belongs to BaseClass, but Foo should beexcluded from touching it

�������� ��������� ���������� �����

� Private here means only the aspect can access it, the classes can’t touch it

aspect Speci al Fi el d {pr i vat e BaseCl ass. MyFi el d f i el d;publ i c voi d BaseCl ass. pr ocess( ) {

… can access myFi el d}

publ i c voi d Bar . pr ocess( ) { … can access myFi el d}

publ i c voi d Czar . …}

Page 12: cseweb.ucsd.edu · The AspectJ Language Semantics of Advice (dynamic) Open Classes (static) ...

12

0�� ���������������

� http://eclipse.org/aspectj/� Or just google “aspectj”

���� �������� ��� �[Intelligent thinking] is that one is willing to study in depth an

aspect of one's subject matter in isolation for the sake of its own consistency, all the time knowing that one is occupying oneself only with one of the aspects.

We know that a program must be correct and we can study it from that viewpoint only; we also know that it should be efficient and we can study its efficiency on another day, so to speak. [...]

Nothing is gained by tackling these various aspects simultaneously. It is what I sometimes have called “the separation of concerns,” which, even if not perfectly possible, is yet the only available technique for effective ordering of one’s thoughts, that I know of.–Edsger W.Dijkstra, “On the role of scientific thought.”