Upload
vidya
View
256
Download
0
Embed Size (px)
Citation preview
8/11/2019 Aspectj Tutorial
1/101
1
AspectJ Tutorial1
Aspect-Oriented Programmingwith AspectJ
the AspectJ.org team
Xerox PARC
Bill Griswold, Erik Hilsdale, Jim Hugunin,
Mik Kersten, Gregor Kiczales, Jeffrey Palm
partially funded by DARPA under contract F30602-97-C0246
this tutorial is about...
using AOP and AspectJ to: improve the modularity of crosscutting concerns
design modularity
source code modularity
development process
aspects are two things: concerns that crosscut [design level]
a programming construct [implementation level]
enables crosscutting concernsto be captured in modular units
AspectJ is: is an aspect-oriented extension to Java that supports
general-purpose aspect-oriented programming
8/11/2019 Aspectj Tutorial
2/101
2
problems like
where is logging in org.apache.tomcat red shows lines of code that handle logging
not in just one place
not even in a small number of places
logging is not modularized
problems like
/**= ================== =================== =================== ===========**TheApacheSoftwareLicense,Version1.1**Copyright(c)1999TheApacheSoftwareFoundation.Allrights*reserved.**Redistributionanduseinsourceandbinaryforms,withorwithout*modification,arepermittedprovidedthatthefollowingconditions*aremet:**1.Redistributionsofsourcecodemustretaintheabovecopyright* notice,thislistofconditionsandthefollowingdisclaimer.**2.Redistributionsinbinaryformmustreproducetheabovecopyright* notice,thislistofconditionsandthefollowingdisclaimer in* thedocumentationand/orothermaterialsprovidedwiththe* distribution.**3.Theend-userdocumentationincludedwiththeredistribution,if* any,mustincludethefollowingacknowlegement:* "Thisproductincludessoftwaredevelopedbythe* ApacheSoftwareFoundation(http://www.apache.org/)."* Alternately,thisacknowlegementmayappearinthesoftware
itself,* ifandwhereversuchthird-partyacknowlegementsnormallyappear.**4.The names"TheJakartaProject","Tomcat",and"ApacheSoftware* Foundation"mustnotbeusedtoendorseorpromoteproducts
derived* fromthissoftwarewithoutpriorwrittenpermission.Forwritten* permission,[email protected].**5.Productsderivedfromthissoftwaremaynotbecalled"Apache"* normay"Apache"appearintheirnameswithoutpriorwritten* permissionoftheApacheGroup.**THISSOFTWAREISPROVIDED ASIS''ANDANYEXPRESSEDORIMPLIED*WARRANTIES,INCLUDING,BUTNOTLIMITEDTO,THEIMPLIEDWARRANTIES*OFMERCHANTABILITYANDFITNESSFORAPARTICULARPURPOSEARE*DISCLAIMED.INNOEVENTSHALLTHEAPACHESOFTWAREFOUNDATIONOR*ITSCONTRIBUTORSBELIABLEFORANYDIRECT,INDIRECT,INCIDENTAL,*SPECIAL,EXEMPLARY,ORCONSEQUENTIALDAMAGES(INCLUDING,BUTNOT*LIMITEDTO,PROCUREMENTOFSUBSTITUTEGOODSORSERVICES;LOSSOF*USE,DATA,ORPROFITS;ORBUSINESSINTERRUPTION)HOWEVERCAUSEDAND*ONANYTHEORYOFLIABILITY,WHETHERINCONTRACT,STRICTLIABILITY,*ORTORT(INCLUDINGNEGLIGENCEOROTHERWISE)ARISINGINANYWAYOUT*OFTHEUSEOF THISSOFTWARE,EVENIFADVISEDOFTHEPOSSIBILITYOF*SUCH DAMAGE.*= ================== =================== =================== ===========**Thissoftwareconsistsof voluntarycontributionsmadebymany*individualsonbehalfoftheApacheSoftwareFoundation.Formore*informationontheApacheSoftwareFoundation,pleasesee*.**[Additionalnotices,ifrequiredbypriorlicensingconditions]**/
packageorg.apache.tomcat.session;importorg.apache. tomcat.core.*;importorg.apache.tomcat.util.StringManager;importjava.io.*;importjava.net.*;importjava.u til.*;importjavax.servlet.*;importjavax.servlet.http.*;
/***Coreimplementationofanapplicationlevelsession**@authorJamesDuncanDavidson[[email protected]]*@authorJasonHunter[[email protected]]*@author JamesTodd [[email protected]]*/
publicclassApplicationSessionimplementsHttpSession{privateStringManagersm=
StringManager.getManager( "org.apache.tom cat.session");privateHashtablevalues=newHashtable();privateStringid;privateServerSessionserverSession;privateContextcontext;privatelongcreationTime=System.currentTimeMillis();;privatelongthisAccessTime=creationTime;privatelonglastAccessed=creationTime;privateintinactiveInterval= -1;privatebooleanvalid=true;ApplicationSession(Stringid,ServerSessionserverSession,
Contextcontext){this.serverSession=serverSession;this.context=co ntext;this.id=id;this.inactiveInterval=context.getSessionTimeOut();
if(this.inactiveInterval!=-1) {this.inactiveInterval*=60;
}}ServerSessiongetServerSession() {
returnserverSession;}
/***Calledbycontextwhenrequestcomesinsothataccessesand*inactivitiescanbedealtwithaccordingly.*/
voidaccessed(){//setlastaccessedtothisAccessTimeasitwillbeleftover//fromthepreviousaccesslastAccessed= thisAccessTime ;thisAccessTime= System.currentTimeMillis( );
validate();}voidvalidate(){
//ifwehavean inactiveinterval,checktoseeifwe'veexceededitif(inactiveInterval!=-1){intthisInterval=
(int)(System. currentTimeMillis( )-lastAccessed)/1000;if (thisInterval>inactiveInterval){
invalidate();}
}}//HTTPSESSIONIMPLEMENTATIONMETHODS
publicStringgetId(){if(valid){returnid;}else{Stringmsg=sm.getString("applicationSession.session.ise");
throw newIllegalStat eException(m sg);}
}publiclonggetCreationTime() {
if(valid){returncreationTime;
}else{Stringmsg=sm.getString("applicationSession.session.ise");throw newIllegalStat eException(m sg);
}}
/****@deprecated*/
publicHttpSessionContextgetSessionContext(){returnnewSessionContextImpl();}
publiclonggetLastAccessedTime(){if(valid){returnlastAccessed;
}else{Stringmsg=sm.getString("applicationSession.session.ise");
throw newIllegalStat eException(m sg);}
}
publicvoidinvalidate(){serverSession.removeApplicationSession (context);
//removeeverythinginthesessionEnumeration enum= values.keys();
while(enum.hasMoreElements( ) ) {Stringname=(String)enum.nextElement();removeValue(name);
}valid=false;
}
publicbooleanisNew() {if(!valid){Stringmsg=sm.getString("applicationSession.session.ise");throw newIllegalStat eException(m sg);
}
if(thisAccessTime==creationTime){returntrue;}else{returnfalse;
}}
/***@deprecated*/
publicvoidputValue(Stringname,Objectvalue){setAttribute(name, value);}
publicvoidsetAttribute(Stringname,Objectvalue){if(!valid){Stringmsg=sm.getString("applicationSession.session.ise");throw newIllegalStat eException(m sg);
}
if(name==null){Stringmsg=sm.getString("applicationSession.value.iae");throw newIllegalArgumentE xception (msg);
}
removeValue(name);//removeanyexistingbinding
if(value!=null&&valueinstanceofHttpSessionBindingListener){HttpSessionBindingEvente=newHttpS essionBindingEvent(this,name );
((HttpSessionBindingListener)value).valueBound(e);}values.put(name,value);
}
/***@deprecated*/publicObjectgetValue(Stringname){returngetAttribute (name);
}
publicObjectgetAttribute(Stringname){if(!valid){Stringmsg=sm.getString("applicationSession.session.ise");
throw newIllegalStat eException(m sg);}
if(name==null){Stringmsg=sm.getString("applicationSession.value.iae");
throw newIllegalArgumentE xception (msg);}
returnvalues.get(name);}
/***@deprecated*/
publicString[]getValueNames(){Enumeratione =getAttributeNames();Vectornames=newVector();
while(e.hasMoreElements()){names.addElement(e.nextElement());
}String[ ]valueNames=n ewString[names. size()];
names.copyInto(valueNames);
returnvalueNames ;}
publicEnumerationgetAttributeNames(){if(!valid){Stringmsg=sm.getString("applicationSession.session.ise");throw newIllegalStat eException(m sg);
}
HashtablevaluesClone= (Hashtable)values.clone();return(Enumeration)valuesClone.keys();
}
/***@deprecated*/
publicvoidremoveValue(Stringname){removeAttribute(name);
}publicvoidremoveAttribute(Stringname){
if(!valid){Stringmsg=sm.getString("applicationSession.session.ise");
throw newIllegalStat eException(m sg);}if(name==null){Stringmsg=sm.getString("applicationSession.value.iae");
throw newIllegalArgumentE xception (msg);}Objecto =values.get(name);
if(oinstanceofHttpSessionBindingListener) {HttpSessionBindingEvente=
newHttpS essionBindingEvent(this,name );((HttpSessionBindingListener)o).valueUnbound (e);
}
values.remo ve(name);}
publicvoidsetMaxInactiveInterval(intinterval){if(!valid){Stringmsg=sm.getString("applicationSession.session.ise");
throw newIllegalStat eException(m sg);}
inactiveInterval =interval;}
publicintgetMaxInactiveInterval(){if(!valid){Stringmsg=sm.getString("applicationSession.session.ise");
throw newIllegalStat eException(m sg);}returninactiveInt erval;
}}
//--------------- -------------- -------------- --------------- -------------
ApplicationSessionpackageorg.apache.tomcat.session;
importjava.io.IOException;importjava.io.ObjectInputStream ;importjava.io.ObjectOutputStream;importjava.io.Serializable;importjava.util. Enumeration;importjava.util.Hashtable;importjava.util .Vector;importjavax.servlet.ServletException ;importjavax.servlet.http.HttpSession;importjavax.servlet.http.HttpSessionBindingEvent ;importjavax.servlet.http.HttpSessionBindingListener;importjavax.servlet.http.HttpSessionContext ;importorg.apache.tomcat.catalina.*;importorg.apache.tomcat.util.StringManager;
/***Standard implementationof theSession
interface.Thisobjectis*serializable,sothatitcan bestoredinpersistentstorageortransferred*toadifferentJVMfordistributablesession
support.* < p > *IMPLEMENTATIONNOTE:An instanceofthis
classrepresentsboththe*internal(Session)andapplicationlevel(HttpSession)viewofthesession.*However,becausetheclassitselfisnotdeclared
public,Javalogicoutside*of theorg.apache .tomcat.session
packagecannotcastan*HttpSessionviewofthisinstancebacktoaSessionview.**@authorCraigR.McClanahan*@version$Revision:1.2$$Date:2000/05/15
17:54:10$*/
finalclassStandardSessionimplementsHttpSession,Session{
//--------------- --------------------- -----------------------Constructors
/***ConstructanewSessionassociatedwiththespecifiedManager.**@parammanagerThemanagerwithwhichthis
Sessionisassociated*/
publicStandardSession(Managermanager){super();this.manager=man ager;
}
//--------------- --------------------- -----------------InstanceVariables
/***ThecollectionofuserdataattributesassociatedwiththisSession.
*/privateHashtableattributes=newHashtable();
/***Thetimethissessionwascreated,in
millisecondssincemidnight,*January1, 1970GMT.*/
privatelongcreationTime= 0L;
/***ThesessionidentifierofthisSession.*/
privateStringid=null;
/***Descriptiveinformationdescribingthis
Sessionimplementation.*/privatestaticfinalStringinfo=
"StandardSession/1.0";
/***ThelastaccessedtimeforthisSession.*/
privatelonglastAccessedTime=creationTime;
/***TheManagerwithwhichthisSessionisassociated.*/
privateManagermanager=null;
/***Themaximumtimeinterval,inseconds,betweenclientreques tsbefore
*theservletcontainermay invalidatethissession.Anegativetime
*indicatesthatthesessionshouldnevertimeout.*/privateintmaxInactiveInterval= -1;
/***Flagindicatingwhetherthissessionisnewornot.*/
privatebooleanisNew=true;
/***Flagindicatingwhetherthissessionisvalidornot.
*/privatebooleanisValid=false;
/***Thestringmanagerforthispackage.*/
privateStringManagersm=
StringManager.getManager("org.apache .tomcat.session");
/***TheHTTPsessioncontextassociatedwiththis
session.*/privatestaticHttpSessionContextsessionContext
=null;
/***Thecurrentaccessedtimeforthissession.*/
privatelongthisAccessedTime=creationTime;
//--------------- --------------------- -----------------SessionProperties
/***Setthecreationtimeforthissession.Thismethodiscalledbythe
*ManagerwhenanexistingSessioninstanceisreused.
**@paramtimeThenewcreationtime*/
publicvoidsetCreationTime(longtime){
this.creationTime= time;this.lastAccessedTime =time;this. thisAccessedTime =time;
}
/***Returnthesessionidentifierforthissession.*/
publicStringgetId(){
return(this.id);}
/***Setthesessionidentifierforthissession.**@paramidThenewsessionidentifier*/
publicvoidsetId(Stringid){
if((this.id!=null)&&(manager!=null)&&(managerinstanceofManagerBase))((ManagerBase)manager).remove(this);
this.id=id;
if((manager!=null)&&(managerinstanceofManagerBase))((ManagerBase)manager).add(this);
}
/***Returndescrip tiveinformation aboutthisSessionimplementationand
*thecorrespondingversionnumber,intheformat
*/.*/
publicStringgetInfo(){
return(this.info);
}
/***Returnthelasttimetheclientsentarequest
associatedwit hthis*session,asthenumberofmillisecondssincemidnight,January1,1970*GMT.Actionsthatyourapplicationtakes,
suchasgettingorsetting*avalueassociatedwiththesession,donot
affecttheaccesstime.*/publiclonggetLastAccessedTime(){
return(this.lastAccessedTime );
}
/***ReturntheManagerwithinwhichthisSession
isvalid.*/
publicManagergetManager() {return(this.manager);
}
/***SettheManagerwithinwhichthisSessionis
valid.**@parammanagerThenewManager*/publicvoidsetManager(Managermanager){
this.manager=man ager;
}
/***Returnthemaximumtimeinterval,inseconds,
betweenclientrequests*beforetheservletcontainerwillinvalidate
thesession.Anegative*timeindicatesthatthesessionshouldnevertimeout.
**@exception IllegalStateException ifthis
methodiscalledon*aninvalidatedsession*/
publicintgetMaxInactiveInterval(){
return(this.maxInactiveInterval);
}
/***Setthemaximumtimeinterval,inseconds,
betweenclientrequests*beforetheservletcontainerwillinvalidatethesession.Anegative*timeindicatesthatthesessionshouldnever
timeout.**@paramintervalThenewmaximuminterval*/publicvoidsetMaxInactiveInterval(intinterval)
{
this.maxInactiveInterval =interval;
}
/***ReturntheHttpSessionforwhichthis
object*isthefacade.*/
publicHttpSessiongetSession(){
return((HttpSession)this);
}
//-------------- ------------------------ -----------SessionPublicMethods
/***Updatetheaccessedtimeinformationforthissession.
Thismethod*shouldbecalledbythecontextwhenarequestcomesin
foraparticular*session,eveniftheapplicationdoesnotreferenceit.*/
publicvoidaccess(){
this.lastAccessedTime =this.thisAccessedTime;this.thisAccessedTime =System. currentTimeMillis( );this.isNew=false;}
/***Performtheinternalprocessingrequiredtoinvalidate
thissession,*withouttriggeringanexceptionifthesessionhasalreadyexpired.
*/publicvoidexpire(){
//Removethissessionfromourmanager'sactivesessionsif((manager!=null)&&(managerinstanceof
ManagerBase))((ManagerBase)manager).remove(this);
//UnbindanyobjectsassociatedwiththissessionVectorresults=newVector();Enumerationattrs=getAttributeNames();
while(attrs.hasMoreElements()) {Stringattr=(String)attrs.nextElement();results.addElement(attr);
}Enumerationnames=results.elements();while(names.hasMoreElements()) {
Stringname=(String)names.nextElement();removeAttribute (name);
}//MarkthissessionasinvalidsetValid(false);
}
/***Releaseallobjectreferences,andinitializeinstance
variables,in*preparationforreuseofthisobject.*/
publicvoidrecycle(){//Resettheinstancevariablesassociatedwiththis
Sessionattributes.clear();creationTime= 0L;id=null;lastAccessedTime= 0L;
manager=null;maxInactiveInterval= -1;isNew=true;isValid=false;//TellourManagerthatthisSessionhasbeenrecycledif((manager!=null)&&(managerinstanceof
ManagerBase))((ManagerBase)manager).recycle(this);
}
//------------ -------------------- ---------------- SessionPackage Methods
/***ReturntheisValidflagforthissession.*/
booleanisValid() {
return(this.isValid);}
/***SettheisNewflagforthissession.**@paramisNewThenewvaluefortheisNew
flag*/
voidsetNew(booleanisNew){this.isNew=isNew;
}
/***SettheisValidflagforthissession.**@paramisValidThenewvalueforthe
isValidflag*/
voidsetValid(booleanisValid){this.isValid= isValid;
}
//-------------- ------------------------ -----------HttpSessionProperties
/***Returnthetimewhenthissessionwascreated,in
millisecondssince*midnight,January 1,1970GMT.**@exceptionIllegalStateExceptionifthismethodis
calledonan* invalidatedsession*/publiclonggetCreationTime() {
return(this.creationTime);
}
/***Returnthesessioncontextwithwhichthissessionis
associated.**@deprecatedAsofVersion2.1,thismethodisdeprecatedandhasno* replacement. Itwillberemovedinafutureversionof
the*Java ServletAPI.*/
publicHttpSessionContextgetSessionContext(){if(sessionContext==null)sessionContext=newStandardSessionContext();
return(sessionContext);
}
//------------- --------------------- ------------HttpSessionPublicMethods
/***Returntheobjectboundwiththespecifiednameinthis
session,or*nullifnoobjectisboundwiththatname.**@paramnameNameoftheattributetobereturned**@exceptionIllegalStateExceptionifthismethodis
calledonan* invalidatedsession*/
publicObjectgetAttribute(Stringname){return (attributes.get(name ));
}
/***ReturnanEnumerationof
Stringobjects*containingthenamesoftheobjectsboundtothis
session.**@exceptionIllegalStateExceptionifthismethodis
calledonan* invalidatedsession
*/publicEnumerationgetAttributeNames(){return(attributes.keys());
}
/***Returntheobjectboundwiththespecifiednameinthissession,or
*nullifnoobjectisboundwiththatname.**@paramnameNameofthevaluetobereturned**@exceptionIllegalStateExceptionifthismethodis
calledonan* invalidatedsession**@deprecatedAsofVersion2.2,thismethodisreplaced
by *getAttribute()*/
publicObjectgetValue(Stringname){
return(getAttribute(name));}
/***Returnthesetofnamesofobjectsboundtothis
session. Ifthere*arenosuchobjects,azero-lengtharrayisreturned.**@exceptionIllegalStateExceptionifthismethodis
calledonan* invalidatedsession**@deprecatedAsofVersion2.2,thismethodisreplaced
by*getAttributeNames()*/
publicString[]getValueNames(){Vectorresults=newVector();Enumerationattrs=getAttributeNames();
while(attrs.hasMoreElements()) {Stringattr=(String)attrs.nextElement();results.addElement(attr);
}Stringnames[]= newString[results.size()];for(inti=0;i,thecont ainercalls*valueBound()ontheobject.**@paramnameNametowhichtheobjectisbound,cannotbenull*@paramvalueObjecttobebound,cannotbenull**@exceptionIllegalStateExceptionifthismethodiscalledonan* invalidatedsession**@deprecatedAsofVersion2.2,thismethodisreplacedby*setAttribute()*/
publicvoidputValue(Stringname,Objectvalue){
setAttribute(name, value);
}
/***Removetheobjectboundwiththespecifiednamefromthissession.If*thesessiondoesnothaveanobjectboundwiththisname,thismethod*doesnothing.*
*Afterthismethodexecutes,andiftheobjectimplements*HttpSessionBindingListene r< /code>,thecont ainercalls*valueUnbound ()ontheo bject.**@paramnameNameoftheobjecttoremovefromthissession.**@exceptionIllegalStateExceptionifthismethodiscalledonan* invalidatedsession*/
publicvoidremoveAttribute(Stringname){synchronized(attributes){Objectobject= attributes.get (name);if(object==null)
return;attributes.remove(n ame);// System.out.println("Removingattribute"+name);if(object instanceof HttpSessionBindingListener){
((HttpSessionBindingListener) object).valueUnbound(newHttpSessionBindi ngEvent((HttpSession)this,name));
}}
}
/***Removetheobjectboundwiththespecifiednamefromthissession.If*thesessiondoesnothaveanobjectboundwiththisname,thismethod*doesnothing.*
*Afterthismethodexecutes,andiftheobjectimplements*HttpSessionBindingListene r< /code>,thecont ainercalls*valueUnbound ()ontheo bject.**@paramnameNameoftheobjecttoremovefromthissession.**@exceptionIllegalStateExceptionifthismethodiscalledonan* invalidatedsession**@deprecatedAsofVersion2.2,thismethodisreplacedby*removeAttribute()*/
publicvoidremoveValue(Stringname){
removeAttribute(name);}
/***Bindanobjecttothissession,usingthespecifiedname.Ifanobject*ofthesamenameisalreadyboundtothissession,theobjectis*replaced.*
*Afterthismethodexecutes,andiftheobjectimplements*HttpSessionBindingListene r< /code>,thecont ainercalls*valueBound()ontheobject.**@paramnameNametowhichtheobjectisbound,cannotbenull*@paramvalueObjecttobebound,cannotbenull**@exceptionIllegalArgumentExceptionifanattemptismadetoadda* n o n-serializableobjectinanenvironmentmarkeddistributable.*@exceptionIllegalStateExceptionifthismethodiscalledonan* invalidatedsession*/
publicvoidsetAttribute(Stringname,Objectvalue){
if((manager!=null)&&manager.getDistributable()&&!(valueinstanceof Serializable ))throw newIllegalArgument Exception
(sm.getString("standardSession.setAttribute.iae"));
synchronized(attributes){removeAttribute (name);attributes.put(name,value);if(valueinstanceofHttpSessionBindingListener)
((HttpSessionBindingListener )value). valueBound(newHttpSessionBindi ngEvent((HttpSession)this,name));
}
}
//--------------- ----------------------- ------ HttpSessionP rivateMethods
/***Readaserializedversionofthissessionobjectfromthespecified*objectinput stream.*
*IMPLEMENTATIONNOTE:ThereferencetotheowningManager*isnotrestoredbythismethod,andmustbesetexplicitly.**@paramstreamTheinputstreamtoreadfrom**@exceptionC lassNotFoun dExceptionif anunknownclass isspecified*@exceptionIOExceptio nif aninput/output erroroccurs*/
privatevoidreadObject(ObjectInpu tStreamstream)throwsClassNotFoundException,IOException{
//Deserializethescalarinstancevariables(exceptManager)creationTime=((Long)stream.readObject()).longValue();id=(String)stream.readObject();lastAccessedTime=((Long)stream.readObject()).longValue();maxInactiveInterval=((Integer)stream.readObject()).intValue();isNew=((Boolean )stream. readObject()).booleanValue();isValid=((Boolean)stream.readObject()).booleanValue();
//Deserializetheattributecountandattributevaluesintn=((Integer)stream.readObject()).intValue();for(inti=0;i *LifecycleconfigurationofthiscomponentassumesanXMLnode*inthefollowingformat:** **whereyoucanadjustthefollowingparameters,withdefaultvalues*insquarebrackets:**checkInterval-Theinterval(inseconds)betweenbackground* threadchecksforexpiredsessions.[60]*maxActiveSessions- Themaximumnumberofsessionsallowedto* beactiveatonce,or-1fornolimit.[-1]*maxInactiveInterval -Thedefaultmaximumnumberofsecondsof* inactivitybeforewhichtheserv letcontainerisallowedtotimeout* asession,or-1fornolimit.Thisvalueshouldbeoverriddenfrom* thedefaultsessiontimeoutspecifiedinthewebapplicationdeployment* descriptor,ifany.[- 1]***@authorCraigR.McClanahan*@version$Revision:1.1.1.1$$Date:2000/05/0221:28:30$*/
publicfinalclassStandardManagerextendsManagerBaseimplementsLifecycle,Runnable{
//-------------- -------------------- ------------------- InstanceVariables
/***Theinterval(inseconds)betweenchecksforexpiredsessions.*/
privateintcheckInterval= 60;
/***Hasthiscomp onentbeenco nfiguredyet?*/
privatebooleanconfigured=false;
/***Thedescrip tiveinformation aboutthis implementation.*/
privatestaticfinalStringinfo="StandardManager/1.0";
/***ThemaximumnumberofactiveSessionsallowed,or-1fornolimit.*/
protectedintmaxActiveSessions= -1;
/***Thestringmanagerforthispackage.*/
privateStringManagersm=StringManager.getManager( "org.apache.tom cat.session");
/***Hasthiscomponentbeenstartedyet?*/
privatebooleanstarted=false;
/***Thebackground thread.*/
privateThreadthread=null;
/***Thebackgroundthreadcompletionsemaphore.*/
privatebooleanthreadDone=false;
/***Nametoregisterforthebackgroundthread.*/
privateStringthreadName= "StandardManager" ;
//--------------- ----------------------- ----------------------- Properties
/***Returnthecheckinterval(inseconds)forthisManager.*/publicintgetCheckInterval() {
return(this.checkInterval);
}
/***Setthecheckinterval(inseconds)forthisManager.**@paramcheckIntervalThenew checkinterval*/publicvoidsetCheckInterval(intcheckInterval){
this.checkInterval=checkInterval;
}
/***ReturndescriptiveinformationaboutthisManagerimplementationand*thecorrespondingversionnumber,intheformat*/.*/publicStringgetInfo(){
return(this.info);
}
/***ReturnthemaximumnumberofactiveSessionsallowed,or-1for*nolimit.*/
publicintgetMaxActiveSessions(){return(this.maxActiveSessions);
}
/***SetthemaximumnumberofactivesSessionsallowed,or-1for*nolimit.**@parammax Thenewmaximumnumberofsessions*/publicvoidsetMaxActiveSessions(intmax){
this.maxActiveSessions=max;
}
//---------- -------------- -------------- -------------- -----PublicMethods
/***Constructandreturnanewsessionobject,basedonthedefault*settingsspecifiedbythisManager'sproperties.Thesession*idwillbeassignedbythismethod,andavailableviathegetId()*methodofthereturnedsession.Ifa newsessioncannotbecreated*foranyre ason,return null.**@exceptionIllegalStateExceptionif anewsessioncannotbe*instantiatedforanyreason*/
publicSessioncreateSession (){
if((maxActiveSessions>=0)&&(sessions.size()>= maxActiveSessions))throw newIllegalState Exception
(sm.getString("standardManager.createSession.ise"));
return(super.createSession());
}
//---------------- ------------------------ -------------- LifecycleMethod s
/***Configurethiscomponent,basedonthespecifiedconfiguration*parameters. Thismethodshouldbecalledimmediatelyafterthe*componentinstanceiscreated,andbeforestart()*iscalled.**@paramparametersConfigurationparametersforthiscomponent*(FIXME:Whatobjecttypeshouldthisreallybe?)**@exceptionIllegalStateExceptionif thiscomponenthasalreadybeen*configuredand/orstarted*@exceptionLifecycleExceptionifthiscomponentdetectsafatalerror*intheconfigurationparametersitwasgiven*/
publicvoidconfigure(Nodeparameters)throwsLifecycleException{
//Validateandupdateourcurrentcomponentstateif(configured)throw newLifecycleException
(sm.getString("standardManager.alreadyConfigured"));configured=true;if(parameter s==null)return;
//Parseandprocessourconfigurationparametersif(!("Manager".equals(parameters.getNodeName ())))return;
NamedNodeMapattributes=parameters.getAttributes();Nodenode=null;node= attributes.getNamedItem("checkInterval");if(node!=null){try{
setCheckInterval (Integer.parseInt(node.getNo deValue()));}catch(Throwablet) {
; //XXX-Throwexception?}}
node= attributes.getNamedItem("maxActiveSessions");if(node!=null){try{setMaxActiveSe ssions(Inte ger.parseInt(node.getNodeValue()));}catch(Throwablet) {
; //XXX-Throwexception?}
}node= attributes.getNamedItem("maxInactiveInterval");if(node!=null){try{
setMaxInacti veInterval(Integer.parseInt(node.getNodeValue()));}catch(Throwablet) {
; //XXX-Throwexception?}}
}
/***Prepareforthebeginningofactiveuseofthepublicmethodsofthis*component.Thismethodshouldbecalledafterconfigure(),*andbeforeanyofthepublicmethodsofthecomponentareutilized.**@exceptionIllegalStateExceptionif thiscomponenthasnotyetbeen*configured(ifrequiredforthiscomponent)*@exceptionIllegalStateExceptionif thiscomponenthasalreadybeen*started*@exceptionLifecycleExceptionifthiscomponentdetectsafatalerror* thatpreventsthiscomponentfrombeingused*/
publicvoidstart()throwsLifecycleException {
//Validateandupdateourcurrentcomponentstateif(!configured)throw newLifecycleException
(sm.getString("standardManager.notConfigured"));if(started)throw newLifecycleException
(sm.getString("standardManager.alreadyStarted "));started=true;//StartthebackgroundreaperthreadthreadStart();
}
/***Gracefullyterminatetheactiveuseofthepublicmethodsofthis*component.Thismethodshouldbethelastonecalledonagiven*instanceofthi scomponent.**@exceptionIllegalStateExceptionifthiscomponenthasnotbeenstarted*@exceptionIllegalStateExceptionif thiscomponenthasalready* beenstopped*@exceptionLifecycleExceptionifthiscomponentdetectsafatalerror* thatneedstobe reported*/publicvoidstop()throwsLifecycleException{
//Validateandupdateourcurrentcomponentstateif(!started)throw newLifecycleException
(sm.getString("standardManager.notStarted"));started=false;
//StopthebackgroundreaperthreadthreadStop();
//Expireall activesessionsSessionsessions[]=findSessions();for(inti=0;i *XXX-Atpresent,useofStandardManagerishardcoded,
*andlifecycleconfigurationisnotsupported.* < p > *IMPLEMENTATIONNOTE:Oncewecommittothenew
Manager/Session*paradigm,Iwouldsuggestmovingthelogicimplementedherebackinto
*thecorelevel.TheTomcat.Next"Manager"interfaceactsmorelikea*collectionclass,andhasminimalknowledgeofthedetailedrequest*processingsemanticsofhandlingsessions.* < p >
*XXX-Atpresent,thereisnoway(viatheSessionManagerinterface)for
*aContexttotelltheManagerthatwecreatewhatthedefaultsession*timeoutforthiswebapplication(specifiedinthedeployment
descriptor)*shouldbe.**@authorCraigR.McClanahan
*/
publicfinalclassStandardSessionManagerimplementsSessionManager{
//----------- -------------- ------------- -------------- -------Constructors
/***CreateanewSessionManagerthatadaptstothecorresponding
Manager*implementation.*/
publicStandardSessionManager(){
manager=newStandardManager();if(managerinstanceofLifecycle){
try{((Lifecycle)manager).configure(null);((Lifecycle) manager).start();
}catch(LifecycleException e){
thrownewIllegalStateException(""+e);}
}
}
//---------------- -------------------- ----------------- InstanceVariables
/***TheManagerimplementationweareactuallyusing.*/
privateManagermanager=null;
// ----------------------- -------------------------- -------- PublicMethods
/***Markthespecifiedsession'slastaccessedtime.Thisshouldbe*calledforeachrequestbyaRequestInterceptor.
**@paramsessionThesessiontobemarked*/
publicvoidaccessed(Contextctx,Requestreq,Stringid){
HttpSessionsession=findSession( ctx,id);if(session==null)return;if(sessioninstanceofSession)((Session)sessio n).access();
//cachetheHttpSession- avoidanotherfindreq.setSession( session);
}
//XXXshouldwethrowexceptionorjustreturnnull??publicHttpSessionfindSession(Contextctx,Stringid){
try{
Sessionsession=manager.findSession(id);if(session!=null)
returnsession.getSession();}catch(IOExceptione){
}return(null);
}
publicHttpSessioncreateSession(Contextctx){returnmanager.createSession().getSession();
}
/***RemoveallsessionsbecauseourassociatedContextisbeingshut
down.**@paramctxThecontextthatisbeingshutdown*/
publicvoidremoveSessions(Contextctx){
//XXXXXXamanagermaybesharedbymultiple//contexts,wejustwanttoremovethesessionsofctx!
//Themanagerwillstillrunafterthat(i.e.keepdatabase//connectionopenif(managerinstanceofLifecycle){try{
((Lifecycle)manager).stop();}catch(LifecycleException e){
thrownewIllegalStateException(""+e);}
}
}
/***Usedbycontexttoconfigurethesessionmanager'sinactivity
timeout.**TheSessionManagermayhavesomedefaultsessiontimeout,the*Contextontheotherhandhasit'stimeoutsetbythedeployment
*descriptor(web.xml).Thismethodletsthe Contextconforgurethe*sessionmanageraccordingtothisvalue.**@paramminutesThesessioninactivitytimeoutinminutes.
*/publicvoidsetSessionTimeOut(intminutes){
if(-1!=minutes){//Themanagerworkswithseconds...
manager.setMaxInactiveInterval(minutes* 60);}
}}
ServerSessionManagerpackageorg.apache.tomcat.session;
importorg.apache.to mcat.util.*;importorg.apache.to mcat.core.*;importjava.io.*;importjava.net.*;importjava.ut il.*;importjavax.servlet.http.*;
/****@authorJamesDuncanDavidson[ [email protected]]*@authorJasonHunter[[email protected]]*@author JamesTodd [[email protected]]*/
publicclassServerSessionManagerimplementsSessionManager{
privateStringManagersm=StringManager.getManager ("org.apache.t omcat.session") ;
privatestaticServerSessionManagermanager;//=newServerSessionManager();protectedintinactiveInterval=-1;
static{manager=newServerSessionManager();
}publicstaticServerSessionManagergetManager(){
returnmanager;}
privateHashtablesessions=newHashtable();privateReaperreaper;privateServerSessionManager (){
reaper= Reaper.getReaper();reaper.setServe rSessionManager(this);reaper.start();
}publicvoidaccessed(Contextctx, Requestreq,Stringid){
ApplicationSessionapS=(ApplicationSession)findSession(ctx,id);if(apS==null)return;
ServerSessionservS =apS.getServerSession();servS.accessed();apS.accessed();
//cacheit -noneedtocomputeitagainreq.setSession( apS);
}publicHttpSessioncreateSession(Contextctx){
StringsessionId=SessionIdGenerator.generateId();ServerSessionsession=newServerSession(sessionId);sessions.put(sessionId,session);if(-1 !=inactiveInterval){session.setMaxInactiveInterval(inactiveInterval) ;
}returnsession.getApplicationSession( ctx,true);
}publicHttpSessionfindSession(Contextctx,Stringid){
ServerSessionsSession=(ServerSession)sessions.get(id);if(sSession==null)return null;
returnsSession.getApplicationSession(ctx, false);}
/ / X X X//sync'dfor safty-- nootherthreadshouldbegettingsomething//fromthiswhilewearereaping.Thisisn'tthemostoptimal//solutionforthis,butwe'lldeterminesomethingelselater.synchronizedvoidreap(){
Enumeration enum= sessions.keys();
while(enum.hasMoreElements( ) ) {Objectkey=enum.nextElement();ServerSessionsession=( ServerSession)sessions.get(key);session.reap();session.validate() ;
}}synchronizedvoidremoveSession(ServerSessionsession){
Stringid=session.getId();
session.invalidate();sessions.remove(id);
}publicvoidremoveSessions(Contextcontext){
Enumeration enum= sessions.keys();
while(enum.hasMoreElements( ) ) {Objectkey=enum.nextElement();ServerSessionsession=( ServerSession)sessions.get(key);
ApplicationSessionappSession=session.getAppli cationSess ion(context,false);
if (appSessi on!=null){appSession.invalidate();}
}}
/***Usedbycontexttoconfigurethesessionmanager'sinactivitytimeout.**TheSessionManagermayhavesomedefaultsessiontimeout,the*Contextontheotherhandhasit'stimeoutsetbythedeployment*descriptor(web.xml).Thismethodletsthe Contextconforgurethe*sessionmanageraccordingtothisvalue.**@paramminutesThesessioninactivitytimeoutinminutes.*/
publicvoidsetSessionTimeOut(intminutes){if(-1!=minutes){//Themanagerworkswithseconds...inactiveInterval=(minutes*60);}
}}
SessionInterceptorpackageorg.apache.tomcat.request;
importorg.apache.to mcat.core.*;importorg.apache.to mcat.util.*;importjava.io.*;importjava.net.*;importjava.ut il.*;importjavax.servlet.http.*;
/***WillprocesstherequestanddeterminethesessionId,andsetit*in theRequest.*Italsomarksthesessionasaccessed.**ThisimplementationonlyhandlesCookiessessions,pleaseextendor*addnewinterceptorsforothermethods.**/
publicclassSessionInterceptorextends BaseInterceptorimplementsRequestInterceptor{
//GS,separatesthesessionidfromthejvmroutestaticfinalcharSESSIONID_ROUTE_SEP='.';intdebug=0;ContextManagercm;
publicSessionInterceptor(){}
publicvoidsetDebug(inti){System.out.print ln("Setdebugto"+i);debug=i;
}
publicvoidsetContextManager(ContextManagercm){this.cm=cm;}
publicintrequestMap(Requestrequest){StringsessionId =null;Cookiecookies[]=request.getCookies();//a ssert!=nul l
for(inti=0;i0)cm.log("XXXRURI="+request.getRequestURI());if((foundAt=request.getRequestURI().indexOf(sig))!=-1){sessionId=request.getRequestURI(). substring(foundAt+ sig.length( ));//rewriteURL,doIneedtodoanythingmore?request.setRequestURI(request.getRequestURI().substring(0,foundAt));sessionId=validateSessionId (request,sessionId );if (sessionId!=null){
request.setReque stedSession IdFromURL(true);}}return0;
}
//XXXwhatisthecorrectbehaviorifthesessionisinvalid?//Wemaystillsetitandjustreturnsessioninvalid.
/**Validateandfix thesessionid.If thesessionisnot validreturnnull.*Itwillalsocleanupthesessionfromload-balancingstrings.*@returnsessionId,ornullifnot valid*/privateStringvalidateSessionId(Requestrequest,StringsessionId){//GS,WepiggybacktheJVMidontopofthe sessioncookie//Separatethem...
if(debug>0)cm.log("OrigsessionId" +sessionId);if(null!=sessionId){intidex=sessionId.lastIndexOf(SESSIONID_ROUTE_SEP);if(idex>0){
sessionId=sessionId.substring(0,idex);}
}if(sessionId!=null&&sessionId.length()!=0){//GS,Wearein aproblemhere,wemayactuallyget//multipleSessioncookies(oneforthe root//contextandonefortherealcontext...oroldsession//cookie.Wemustcheckforvalidityinthecurrentcontext.Contextctx=request.getContext();SessionManagersM =ctx.getSessionManager();if(null!= sM.findSession( ctx,sessionId)){
sM.accessed(ctx,request,sessionId) ;request.setRequestedSessionId(sessionId);if(debug>0)cm.log("Finalsessionid" +sessionId);returnsessionId;}
}returnnull;
}
publicintbeforeBody(Requestrrequest,Responseresponse){StringreqSessionId=response.getSessionId();if(debug>0)cm.log("BeforeBody"+reqSessionId);if(reqSessionId==nul l)return0;
//GS,setthepathattributetothecookie.Thisway//multiplesessioncookiescanbeused,oneforeach//context.StringsessionPath=rrequest.getContext().getPath();if(sessionPath .length()==0){sessionPath=" / " ;
}//GS,piggybackthejvmrouteonthesessionid.if(!sessionPath.equals("/")){StringjvmRoute= rrequest.getJvmRoute();if(null!= jvmRoute){
reqSessionId=reqSessionId+SESSIONID_ROUTE_SEP+jvmRoute;}}
Cookiecookie =new Cookie("JSESSIONID",reqSessionId);
cookie.setMaxAge(- 1);cookie.setPath( sessionPath);cookie.setVersion(1);
response.addH eader(CookieTools.getCookieHeaderName(cookie),CookieTools.getCookieHeaderValue(cookie) );
cookie.setVersion(0);response.addH eader(CookieTools.getCookieHeaderName(cookie),CookieTools.getCookieHeaderValue(cookie) );
return0;}
/**Notificationofcontextshutdown*/
publicvoidcontextShutdown(Contextctx)throwsTomcatException
{if(ctx.getDebug()>0) ctx.log("Removingsessionsfrom"+ ctx);ctx.getSessionManager().removeSessions(ctx);
}
}
ServerSessionpackageorg.apache.tomcat.session;
importorg.apache. tomcat.core.*;importorg.apache.tomcat.util.StringManager;importjava.io.*;importjava.net.*;importjava.u til.*;importjavax.servlet.*;importjavax.servlet.http.*;
/***Coreimplementationofaserversession**@authorJamesDuncanDavidson[[email protected]]*@author JamesTodd [[email protected]]*/
publicclassServerSession{
privateStringManagersm=StringManager.getManager( "org.apache.tom cat.session");
privateHashtablevalues=newHashtable();privateHashtableappSessions=newHashtable();privateStringid;privatelongcreationTime=System.currentTimeMillis();;privatelongthisAccessTime=creationTime;privatelonglastAccessed=creationTime;privateintinactiveInterval= -1;ServerSession(Stringid) {
this.id=id;}
publicStringgetId(){returnid;}
publiclonggetCreationTime() {returncreationTime ;
}publiclonggetLastAccessedTime(){
returnlastAccessed ;}
publicApplicationSessiongetApplicationSession(Contextcontext,booleancreate){ApplicationSessionappSession=
(ApplicationSess ion)appSessions.ge t(contex t);
if(appSession==null&&create){
/ / X X X//synctoensurevalid?
appSession= newApplicationSession(id,this, context);appSessions.put(context,appSession);
}//XXX//makesurethatwehaven'tgoneovertheendofour//inactiveinterval--ifso,invalidateandcreate//a newappSession
returnappSession ;}
voidremoveApplicationSession(Contextcontext){appSessions.remove(context);
}/***Calledbycontextwhenrequestcomesinsothataccessesand*inactivitiescanbedealtwithaccordingly.*/
voidaccessed(){//setlastaccessedtothisAccessTimeasitwillbeleftover//fromthepreviousaccess
lastAccessed= thisAccessTime ;thisAccessTime= System.currentTimeMillis( );
}
voidvalidate()
voidvalidate(){//ifwehavean inactiveinterval,checktoseeif//we'veexceededit
if(inactiveInterval!=-1){intthisInterval=(int)(System. currentTimeMillis( )-lastAccessed)/1000;
if (thisInterval>inactiveInterval){invalidate();ServerSessionManagerssm=
ServerSessio nManager.getManager();
ssm.removeSession(this);}
}}
synchronizedvoidinvalidate(){Enumerationenum=appSessions.keys();
while(enum.hasMoreElements( ) ) {Objectkey=enum.nextElement( );ApplicationSessionappSession=
(ApplicationSession)appSessions.get(key);
appSession .invalidate();}}
publicvoidputValue(Stringname,Objectvalue){if(name==null){Stringmsg=sm.getString("serverSession.value.iae");throw newIllegalArgumentExc eption (msg);
}
removeValue(name);//removeanyexistingbindingvalues.put(name,value);
}publicObjectgetValue(Stringname){
if(name==null){Stringmsg=sm.getString("serverSession.value.iae");
throw newIllegalArgumentExc eption (msg);}
returnvalues.get(name);}
publicEnumerationgetValueNames() {returnvalues.keys();}
publicvoidremoveValue(Stringname){values.remov e(name);
}publicvoidsetMaxInactiveInterval(intinterval){
inactiveInterval =interval;}
publicintgetMaxInactiveInterval(){returninactiveInte rval;}
//XXX//sync'dfor safty--no otherthreadshouldbegettingsomething//fromthiswhilewearereaping.Thisisn'tthemostoptimal//solutionforthis,butwe'lldeterminesomethingelselater.
synchronizedvoidreap(){Enumerationenum=appSessions.keys();
while(enum.hasMoreElements( ) ) {Objectkey=enum.nextElement( );ApplicationSessionappSession=
(ApplicationSession)appSessions.get(key);
appSession .validate();}}
}
session expiration is not modularized
8/11/2019 Aspectj Tutorial
3/101
3
problems like
HTTPRequest
HTTPResponse
Servlet
getCookies ()getRequestURI()(doc)
getSession()getRequestedSessionId()...
getRequest()
setContentType(contentType)getOutptutStream()setSessionId(id)
...
SessionInterceptor
requestMap(request)beforeBody(req, resp)
...
Session
getAttribute(name)setAttribute(name, val)
invalidate()...
session tracking is not modularized
the cost of tangled code
redundant code same fragment of code in many places
difficult to reason about non-explicit structure
the big picture of the tangling isnt clear
difficult to change have to find all the code involved
and be sure to change it consistently
and be sure not to break it by accident
8/11/2019 Aspectj Tutorial
4/101
4
crosscutting concerns
HTTPRequest
Session
HTTPResponse
Servlet
getCookies ()getRequestURI()(doc)
getSession()getRequestedSessionId()...
getAttribute(name)setAttribute(name, val)
invalidate()...
getRequest()
setContentType(contentType)getOutptutStream()setSessionId(id)
...
SessionInterceptor
requestMap(request)beforeBody(req, resp)
...
the AOP idea
crosscutting is inherent in complex systems
crosscutting concerns have a clear purpose
have a natural structure
defined set of methods, module boundary crossings,points of resource utilization, lines of dataflow
so, lets capture the structure of crosscuttingconcerns explicitly... in a modular way
with linguistic and tool support
aspects are well-modularized crosscutting concerns
aspect-oriented programming
8/11/2019 Aspectj Tutorial
5/101
8/11/2019 Aspectj Tutorial
6/101
6
AspectJ is
a small and well-integrated extension to Java
a general-purpose AO language just as Java is a general-purpose OO language
freely available implementation compiler is Open Source
includes IDE support emacs, JBuilder 3.5, JBuilder 4, Forte 4J
user feedback is driving language design
[email protected] [email protected]
currently at 0.8 release 1.0 planned for June 2001
expected benefits of using AOP
good modularity,even for crosscutting concerns
less tangled code
more natural code
shorter code
easier maintenance and evolution easier to reason about, debug, change
more reusable library aspects
plug and play aspects when appropriate
8/11/2019 Aspectj Tutorial
7/101
7
outline
I AOP overview brief motivation, essence of AOP idea
II AspectJ language mechanisms basic concepts, language semantics
III development environment IDE support, running the compiler, debugging etc.
IV using aspects
aspect examples, how to use AspectJ to program
aspects, exercises to solidify the ideas
V related work survey of other activities in the AOP community
looking ahead
AspectJ mechanisms
Part II:
crosscutting in the code
mechanisms AspectJ provides
problem structure
Part IV:
crosscutting in the design, and
how to use AspectJ to capture that
8/11/2019 Aspectj Tutorial
8/101
8
Part II
Basic Mechanisms of AspectJ
goals of this chapter
present basic language mechanisms
using one simple example
emphasis on what the mechanisms do
small scale motivation
later chapters elaborate on
environment, tools
larger examples, design and SE issues
8/11/2019 Aspectj Tutorial
9/101
9
basic mechanisms
1 overlay onto Java join points
points in the execution of Java programs
4 small additions to Java
pointcuts primitive pointcuts
pick out sets of join points and values at those points
user-defined pointcuts
named collections of join points and values
advice
additional action to take at join points in a pointcut
introduction
additional fields/methods/constructors for classes aspect
a crosscutting type
comprised of advice, introduction,
field,constructor and method declarations
a simple figure editor
class Line implements FigureElement{private Point _p1, _p2;
Point getP1() { return_p1; }Point getP2() { return_p2; }
voidsetP1(Point p1) { _p1 = p1; }voidsetP2(Point p2) { _p2 = p2; }
}
class Point implements FigureElement {private int_x = 0, _y = 0;
int getX() { return_x; }int getY() { return_y; }
voidsetX(int x) { _x = x; }voidsetY(int y) { _y = y; }
}
display must be
updated when
objects move
8/11/2019 Aspectj Tutorial
10/101
10
move tracking
collection of figure elements that change periodically
must monitor changes to refreshthe display as needed
collection can be complex
hierarchical
asynchronous events
other examples session liveness
value caching
a Figure
a Line
join points
and returns or
throws
object
receives a
method call
dispatch
dispatch
key points in dynamic call graph
object receives a
method call
and a return or
exception is received
by this method
a method call toanother object
and returns
or throws
8/11/2019 Aspectj Tutorial
11/101
11
join point terminology
11 kinds of join points
method & constructorcall reception join points
method & constructorcall join points method & constructor execution join points
field get & set join points
exception handler execution join points
static & dynamic initialization join points
a Line
dispatch
method call
join points
method call
reception
join points
key points in dynamic call graph
join point terminology
a Line
aFigure
a Point
a Point
the method call join point
corresponding to this
method reception join point
all join points on this slide are
within the control flow of
this join point
repeated calls to
the same method
on the same objectresult in multiple
join points
key points in dynamic call graph
8/11/2019 Aspectj Tutorial
12/101
12
the pointcut construct
each time a Line receives a
void setP1(Point) or void setP2(Point) method call
names certain join points
or
reception of a void Line.setP2(Point) call
name and parametersreception of a void Line.setP1(Point) call
pointcutmoves():receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point));
pointcut designators
primitive pointcut designator, can also be:- calls, executions - instanceof,- gets, sets - within, withincode
- handlers - cflow, cflowtop
pointcutmoves():receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point));
user-defined pointcut designator
8/11/2019 Aspectj Tutorial
13/101
13
pointcutmoves():receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point));
after(): moves() {
< r u n s a f t e r mov es > }
after advice action to take aftercomputation under join points
a Line
after advice runson the way back out
aspectMoveTracking {private boolean_flag = false;public boolean testAndClear() {boolean result = _flag;_flag = false;return result;
}
pointcutmoves():receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point));
after(): moves() {_flag = true;}
}
a simple aspect
aspect defines a
special class that can
crosscut other classes
MoveTracking v1
box means complete running code
8/11/2019 Aspectj Tutorial
14/101
14
without AspectJ
what you would expect calls to set flag are tangled through the code
what is going on is less explicit
class MoveTracking {private static boolean _flag = false;
public static void setFlag() {_flag = true;
}
public static boolean testAndClear() {boolean result = _flag;_flag = false;return result;
}}
class Line {private Point _p1, _p2;
Point getP1() { return _p1; }Point getP2() { return _p2; }
voidsetP1(Point p1) {_p1 = p1;MoveTracking.setFlag();
}voidsetP2(Point p2) {_p2 = p2;MoveTracking.setFlag();
}}
MoveTracking v1
the pointcut constructcan cut across multiple classes
pointcutmoves():receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(voidPoint.setX(int)) ||receptions(voidPoint.setY(int));
8/11/2019 Aspectj Tutorial
15/101
15
aspectMoveTracking {private boolean_flag = false;public boolean testAndClear() {boolean result = _flag;_flag = false;return result;
}
pointcutmoves():receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(voidPoint.setX(int)) ||receptions(voidPoint.setY(int));
after(): moves() {_flag = true;}
}
a multi-class aspectMoveTracking v2
pointcutmoves(FigureElement figElt):instanceof(figElt) &&(receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(voidPoint.setX(int)) ||receptions(voidPoint.setY(int)));
after(FigureElement fe): moves(fe) {
}
using context in advice
pointcut can explicitly expose certain values
advice can use value
demonstrate first, explain in detail afterwards
parameter
mechanism is
being used
8/11/2019 Aspectj Tutorial
16/101
16
context & multiple classesMoveTracking v3
aspectMoveTracking {private Set _movees = new HashSet();public Set getMovees() {
Set result = _movees;_movees = new HashSet();return result;
}
pointcutmoves(FigureElement figElt):instanceof(figElt) &&(receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(voidPoint.setX(int)) ||
receptions(voidPoint.setY(int)));
after(FigureElement fe): moves(fe) {_movees.add(fe);}
}
parameters
variable bound in user-defined pointcut designator
variable in place of type name in pointcut designator
pulls corresponding value out of joinpoints
makes value accessible on pointcutpointcut parameterspointcutmoves(Line l):
receptions(void l.setP1(Point)) ||receptions(void l.setP2(Point));
after(Line line): moves(line) {
}
variable in place of type name
of user-defined pointcut designator
8/11/2019 Aspectj Tutorial
17/101
17
parameters
variable bound in advice
variable in place of type name in pointcut designator
pulls corresponding value out of join points
makes value accessible within advice
pointcut moves(Line l):receptions(void l.setP1(Point)) ||receptions(void l.setP2(Point));
after(Line line): moves(line) {
}
typed variable in place
of type nameadvice parameters
of advice
parameters
value is pulled
right to left across : left side : right side
from pointcut designators to user-defined pointcut designators
from pointcut to advice
pointcutmoves(Line l):receptions(void l.setP1(Point)) ||receptions(void l.setP2(Point));
after(Line line): moves(line) {
}
8/11/2019 Aspectj Tutorial
18/101
18
instanceof
instanceof()
any join point at which
currently executing object is instanceof type (or class) name
instanceof(Point)instanceof(Line)instanceof(FigureElement)
any join point means it matches join points of all 11 kinds method & constructor call join points
method & constructor call reception join points method & constructor execution join points
field get & set join points exception handler execution join points
static & dynamic initialization join points
primitive pointcut designator
pointcutmoves(FigureElement figElt):instanceof(figElt) &&(receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(voidPoint.setX(int)) ||receptions(voidPoint.setY(int)));
after(FigureElement fe): moves(fe) {
}
an idiom for
instanceof() &&
does not further restrict the join points
does pick up the currently executing object (this)
getting object in a polymorphic pointcut
8/11/2019 Aspectj Tutorial
19/101
19
context & multiple classesMoveTracking v3
aspectMoveTracking {private Set _movees = new HashSet();public Set getMovees() {
Set result = _movees;_movees = new HashSet();return result;
}
pointcutmoves(FigureElement figElt):instanceof(figElt) &&(receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(voidPoint.setX(int)) ||
receptions(voidPoint.setY(int)));
after(FigureElement fe): moves(fe) {_movees.add(fe);}
}
without AspectJ
class Line {private Point _p1, _p2;
Point getP1() { return _p1; }Point getP2() { return _p2; }
voidsetP1(Point p1) {_p1 = p1;
}voidsetP2(Point p2) {_p2 = p2;
}}
class Point {private int_x = 0, _y = 0;
int getX() { return_x; }
int getY() { return_y; }
voidsetX(int x) {_x = x;
}voidsetY(int y) {_y = y;
}}
8/11/2019 Aspectj Tutorial
20/101
20
class Line {private Point _p1, _p2;
Point getP1() { return _p1; }Point getP2() { return _p2; }
voidsetP1(Point p1) {_p1 = p1;MoveTracking.setFlag();}voidsetP2(Point p2) {_p2 = p2;MoveTracking.setFlag();}
}
class Point {private int_x = 0, _y = 0;
int getX() { return_x; }int getY() { return_y; }
voidsetX(int x) {_x = x;
}voidsetY(int y) {_y = y;
}}
class MoveTracking {private static boolean _flag = false;
public static void setFlag() {_flag = true;}
public static boolean testAndClear() {boolean result = _flag;_flag = false;return result;
}}
without AspectJMoveTracking v1
class Line {private Point _p1, _p2;
Point getP1() { return _p1; }Point getP2() { return _p2; }
voidsetP1(Point p1) {_p1 = p1;MoveTracking.setFlag();}voidsetP2(Point p2) {_p2 = p2;MoveTracking.setFlag();}
}
class Point {private int_x = 0, _y = 0;
int getX() { return_x; }
int getY() { return_y; }
voidsetX(int x) {_x = x;MoveTracking.setFlag();}voidsetY(int y) {_y = y;MoveTracking.setFlag();}
}
without AspectJMoveTracking v2
classMoveTracking {private static boolean_flag = false;
public static voidsetFlag() {_flag = true;}
public static boolean testAndClear() {boolean result = _flag;_flag = false;return result;
}}
8/11/2019 Aspectj Tutorial
21/101
21
class Line {private Point _p1, _p2;
Point getP1() { return _p1; }Point getP2() { return _p2; }
voidsetP1(Point p1) {_p1 = p1;MoveTracking.collectOne(this);}voidsetP2(Point p2) {_p2 = p2;MoveTracking.collectOne(this);}
}
class Point {private int_x = 0, _y = 0;
int getX() { return_x; }int getY() { return_y; }
voidsetX(int x) {_x = x;MoveTracking.collectOne(this);}voidsetY(int y) {_y = y;MoveTracking.collectOne(this);}
}
class MoveTracking {private static Set _movees = new HashSet();
public static void collectOne(Object o) {_movees.add(o);}
public static Set getmovees() {Set result = _movees;_movees = new HashSet();return result;
}}
without AspectJ
evolution is cumbersome changes in all three classes
have to track all callers
change method name
add argument
MoveTracking v3
with AspectJ
class Line {private Point _p1, _p2;
Point getP1() { return _p1; }Point getP2() { return _p2; }
voidsetP1(Point p1) {_p1 = p1;}voidsetP2(Point p2) {_p2 = p2;}
}
class Point {private int_x = 0, _y = 0;
int getX() { return_x; }int getY() { return_y; }
voidsetX(int x) {_x = x;}voidsetY(int y) {_y = y;}
}
8/11/2019 Aspectj Tutorial
22/101
22
with AspectJ
class Line {private Point _p1, _p2;
Point getP1() { return _p1; }Point getP2() { return _p2; }
voidsetP1(Point p1) {_p1 = p1;}voidsetP2(Point p2) {_p2 = p2;}
}
class Point {private int_x = 0, _y = 0;
int getX() { return_x; }int getY() { return_y; }
voidsetX(int x) {
_x = x;}voidsetY(int y) {_y = y;}
}
aspect MoveTracking {private boolean _flag = false;public boolean testAndClear() {boolean result = _flag;_flag = false;return result;
}
pointcut moves():receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point));
after(): moves() {_flag = true;}
}
MoveTracking v1
class Line {private Point _p1, _p2;
Point getP1() { return _p1; }Point getP2() { return _p2; }
voidsetP1(Point p1) {_p1 = p1;}voidsetP2(Point p2) {_p2 = p2;}
}
class Point {private int_x = 0, _y = 0;
int getX() { return_x; }int getY() { return_y; }
voidsetX(int x) {_x = x;}voidsetY(int y) {_y = y;}
}
with AspectJMoveTracking v2
aspectMoveTracking {private boolean_flag = false;publicboolean testAndClear() {boolean result = _flag;_flag = false;return result;
}
pointcut moves():receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(void Point.setX(int)) ||receptions(void Point.setY(int));
after(): moves() {_flag = true;}
}
8/11/2019 Aspectj Tutorial
23/101
23
class Line {private Point _p1, _p2;
Point getP1() { return _p1; }Point getP2() { return _p2; }
voidsetP1(Point p1) {_p1 = p1;}voidsetP2(Point p2) {_p2 = p2;}
}
class Point {private int_x = 0, _y = 0;
int getX() { return_x; }int getY() { return_y; }
voidsetX(int x) {
_x = x;}voidsetY(int y) {_y = y;}
}
aspectMoveTracking {private Set _movees = new HashSet();public Set getmovees() {
Set result = _movees;_movees = new HashSet();return result;
}
pointcut moves(FigureElement figElt):instanceof(figElt) &&(receptions(voidLine.setP1(Point)) ||receptions(voidLine.setP2(Point)) ||receptions(voidPoint.setX(int)) ||receptions(voidPoint.setY(int)));
after(FigureElement fe): moves(fe) {_movees.add(fe);}
}
with AspectJ
evolution is more modular all changes in single aspect
MoveTracking v3
advice is
before before proceeding at join point
after returning a value to join point
after throwing a throwable to join point
after returning to join point either way
around on arrival at join point gets explicitcontrol over when&if program proceeds
additional action to take at join points
8/11/2019 Aspectj Tutorial
24/101
24
contract checking
pre-conditions check whether parameter is valid
post-conditions
check whether values were set
condition enforcement force parameters to be valid
simple example of before/after/around
pre-condition
aspect PointBoundsPreCondition {
before(Point p, int newX):receptions(voidp.setX(newX)) {
assert(newX >= MIN_X);assert(newX = MIN_Y);assert(newY
8/11/2019 Aspectj Tutorial
25/101
25
post-condition
aspect PointBoundsPostCondition {
after(Point p, int newX):receptions(voidp.setX(newX)) {
assert(p.getX() == newX);}
after(Point p, int newY):receptions(voidp.setY(newY)) {
assert(p.getY() == newY);}
voidassert(boolean v) {if ( !v )throw new RuntimeException();
}}
using after advice
condition enforcement
aspect PointBoundsEnforcement {
around(Point p, int newX) returns void:receptions(voidp.setX(newX)) {
thisJoinPoint.runNext(p, clip(newX, MIN_X, MAX_X));}
around(Point p, int newY) returns void:receptions(voidp.setY(newY)) {
thisJoinPoint.runNext(p, clip(newY, MIN_Y, MAX_Y));}
int clip(int val, intmin, intmax) {returnMath.max(min, Math.min(max, val));
}}
using around advice
8/11/2019 Aspectj Tutorial
26/101
26
special static method
proceed(arg1, arg2)
available only in around advice
means run what would have run if this around advice had not been
defined
other primitive pointcuts
instanceof()within()withincode()
any join point at which
currently executing object is instanceof type or class name
currently executing code is contained within class namecurrently executing code is specified method or constructor
gets(int Point.x)
sets(int Point.x)gets(int Point.x)[val]sets(int Point.x)[oldVal][newVal]
field reference or assignment join points
8/11/2019 Aspectj Tutorial
27/101
27
using field set pointcuts
aspect PointCoordinateTracing {
pointcut coordChanges(Point p, int oldVal, int newVal):sets(intp._x)[oldVal][newVal] ||sets(intp._y)[oldVal][newVal];
after(Point p, int oldVal, int newVal):coordChanges(p, oldVal, newVal) {
System.out.println(At +tjp.getSignature() + field was changed from +oldVal +
to +newVal +.);
}}
special value
thisJoinPoint.
Signature getSignature()
Object[] getParameters()
...
available in any advice
thisJoinPoint is abbreviated to tjp occasionally in these
slides
* introspective subset of reflection consistent with Java
reflective* access to the join point
8/11/2019 Aspectj Tutorial
28/101
28
other primitive pointcuts
calls(voidPoint.setX(int))method/constructor call join points (at call site)
receptions(voidPoint.setX(int))method/constructor call reception join points (at called object)
executions(void Point.setX(int))method/constructor execution join points (at actual called method)
initializations(Point)
object initialization join points
staticinitializations(Point)class initialization join points (as the class is loaded)
context sensitive aspects
aspectMoveTracking {List _movers = new LinkedList();List _movees = new LinkedList();//
pointcutmoveCalls(Object mover, FigureElement movee):instanceof(mover) &&(lineMoveCalls(movee) || pointMoveCalls(movee));
pointcut lineMoveCalls(Line ln):calls(voidln.setP1(Point)) || calls(voidln.setP2(Point));
pointcutpointMoveCalls(Point pt):calls(voidpt.setX(int)) || calls(voidpt.setY(int));
after(Object mover, FigureElement movee):moveCalls(mover, movee) {
_movers.add(mover);_movees.add(movee);}
}
MoveTracking v4a
8/11/2019 Aspectj Tutorial
29/101
29
context sensitive aspects
aspectMoveTracking {List _movers = new LinkedList();List _movees = new LinkedList();//
pointcutmoveCalls(Object mover, FigureElement movee):instanceof(mover) &&(calls(void((Line)movee).setP1(Point)) ||calls(void((Line)movee).setP2(Point)) ||calls(void((Point)movee).setX(int)) ||calls(void((Point)movee).setY(int)));
after(Object mover, FigureElement movee):moveCalls(mover, movee) {
_movers.add(mover);_movees.add(movee);}
}
MoveTracking v4b
does
this
make
sense?
fine-grained protection
class Point implement FigureElement {private int_x = 0, _y = 0;
int getX() { return_x; }int getY() { return_y; }
voidsetX(int nv) { primitiveSetX(nv); }voidsetY(int nv) { primitiveSetY(nv); }
voidprimitiveSetX(int x) { _x = x; }voidprimitiveSetY(int y) { _y = y; }
}
aspect PrimitiveSetterEnforcement {pointcut illegalSets(Point pt):
!(withincode(voidPoint.primitiveSetX(int)) ||withincode(voidPoint.primitiveSetY(int))) &&
(sets(intpt._x) || sets(intpt._y));
before(Point p): illegalSets(p) {throw new Error("Illegal primitive setter call.");
}}
8/11/2019 Aspectj Tutorial
30/101
30
other primitive pointcuts
cflow(po i n t c ut d es i gna t or )cflowtop(po i n t c ut d es i g na t o r )
all join points within the dynamic control flow of any join
point in pointcut designator
cflowtop doesnt start a new one on re-entry
context sensitive aspects
aspect MoveTracking {private Set _movees = new HashSet();public Set getMovees() {
Set result = _movees;_movees = new HashSet();
return result;}
pointcutmoves(FigureElement figElt):instanceof(figElt) &&(receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(voidPoint.setX(int)) ||receptions(voidPoint.setY(int)));
pointcut topLevelMoves(FigureElement figElt):moves(figElt) && !cflow(moves(FigureElement));
after(FigureElement fe): topLevelMoves(fe) {_movees.add(fe);}
}
MoveTracking v5
8/11/2019 Aspectj Tutorial
31/101
31
wildcarding in pointcuts
instanceof(Point)instanceof(graphics.geom.Point)instanceof(graphics.geom.*) any type in graphics.geominstanceof(graphics..*) any type in any sub-package
of graphics
receptions(void Point.setX(int))receptions(public * Point.*(..)) any public method on Pointreceptions(public * *..*.*(..)) any public method on any type
receptions(void Point.getX())receptions(void Point.getY())
receptions(void Point.get*())receptions(void get*()) any getter
receptions(Point.new(int, int))receptions(new(..)) any constructor
* is wild card
.. is multi-part wild card
property-based crosscutting
crosscuts of methods with a common property
public/private, return a certain value, in a particular package
logging, debugging, profiling
log on entry to every public method
package com.xerox.print;public class C1 {
public voidfoo() {A.doSomething();
}
}
package com.xerox.scan;public class C2 {
public int frotz() {A.doSomething();
}public intbar() {A.doSomething();
}
}
package com.xerox.copy;public class C3 {
public String s1() {A.doSomething();
}
}
8/11/2019 Aspectj Tutorial
32/101
32
property-based crosscutting
consider code maintenance another programmer adds a public method i.e. extends public interface this code will still work
another programmer reads this code whats really going on is explicit
aspect PublicErrorLogging {
Log log = new Log();
pointcutpublicInterface ():receptions(public * com.xerox..*.*(..));
after() throwing (Error e): publicInterface() {log.write(e);
}}
neatly captures public
interface of mypackage
aspect statewhat if you want a per-object log?
aspect PublicErrorLoggingof eachobject(PublicErrorLogging.publicInterface()) {
Log log = new Log();
pointcutpublicInterface ():receptions(public * com.xerox..*.*(..));
after() throwing (Error e): publicInterface() {log.write(e);
}
one instance of the aspect for each object
that ever executes at these points
8/11/2019 Aspectj Tutorial
33/101
33
looking up aspect instances
static method of aspects of eachobject()
of eachclass()
of eachcflowroot() returns aspect instance or null
:
static Log getLog(Object obj) {return (PublicErrorLogging.aspectOf(obj)).log;
}}
of each relations
eachobject()
one aspect instance for each
object that is ever this at
the join points
eachclass()
one aspect instance for each class of
object that is ever this at the join points
eachcflowroot()
one aspect instance for each join point
in pointcut, is available at all joinpoints in && cflow()
p1l1
l2p3
p2
FigureElement
Point Line
8/11/2019 Aspectj Tutorial
34/101
34
inheritance & specialization
pointcuts can have additional advice aspect with
concrete pointcut
perhaps no advice on the pointcut
in figure editormoves() can have advice from multiple aspects
module can expose certain well-defined pointcuts
abstract pointcuts can be specialized
aspect with abstract pointcut
concrete advice on the abstract pointcut
a shared pointcut
public class FigureEditor {public pointcutmoves(FigureElement figElt):
instanceof(figElt) &&(receptions(void Line.setP1(Point)) ||receptions(void Line.setP2(Point)) ||receptions(voidPoint.setX(int)) ||receptions(voidPoint.setY(int)));
...
}
aspectMoveTracking {
after(FigureElement fe):FigureEditor.moves(fe) { ... }
...}
8/11/2019 Aspectj Tutorial
35/101
35
a reusable aspect
abstract public aspect RemoteExceptionLogging {
abstract pointcut logPoints();
after() throwing (RemoteException e): logPoints() {log.println(Remote call failed in: +
thisJoinPoint.toString() +( + e + ).);
}}
public aspectMyRMILogging extends RemoteExceptionLogging {
pointcut logPoints():receptions(* RegistryServer.*.*(..)) ||receptions(private * RMIMessageBrokerImpl.*.*(..));
}
abstract
introduction
aspectMoveTracking {private Set _movees = new HashSet();
public Set getMovees() {Set result = _movees;
_movees = new HashSet();return result;
}
introduction FigureElement {private Object lastMovedBy;
public Object getLastMovedBy() { return lastMovedBy; }}
pointcutMoveCalls(Object mover, FigureEl ement movee):instanceof(mover) &&(lineMoveCalls(movee) || pointMoveCalls(movee));
pointcut lineMoveCalls(Line ln):calls(voidln.setP1(Point)) || calls(voidln.setP2(Point));
pointcutpointMoveCalls (Point pt):calls(voidpt.setX(in t)) || calls(voidpt.setY(int));
after(Object mover, FigureElement movee):MoveCalls(mover, movee) {
_movees.add(movee);movee.lastMovedBy = mover;}
}
(like open classes) MoveTracking v6
introduction adds members to target type
public and private are
with respect to enclosing
aspect declaration
8/11/2019 Aspectj Tutorial
36/101
36
calls/receptions/executions
:classMyPoint extends Point {
:int getX() { return super.getX(); }:
}
aspect ShowAccesses {before(): calls(voidPoint.getX()) { }before(): receptions(voidPoint.getX()) { }before(): executions(voidPoint.getX()) { }}
code runs once
(newMyPoint()).getX() code runs oncecode runs twice
differences among
calls/receptions/executions
:classMyPoint extends Point {
:MyPoint() { ... }:
}
aspect ShowAccesses {before(): calls(Point.new()) { }before(): receptions(Point.new()) { }before(): executions(Point.new()) { }}
code runs once
newMyPoint() code runs oncecode runs twice
remember the implicit
super call here!
differences among
8/11/2019 Aspectj Tutorial
37/101
37
summary
dispatch
advicebefore
after
around
of each
inheritance
introduction
pointcuts
-primitive-calls receptions
executions
handlers
gets sets
initializations
instanceof
hasaspect
within withincode
cflow cflowtop
-user-defined-pointcut
declaration
abstract
overriding
join points
method & constructor
calls
call receptions
executions
field
gets
sets
exception handler
executions
initializations
aspectscrosscutting type
of eachobject
class
cflowroot
where we have been
AspectJ mechanisms
Part II:
crosscutting in the code
mechanisms AspectJ provides
problem structure
Part IV:
crosscutting in the design, and
how to use AspectJ to capture that
and where we are going
8/11/2019 Aspectj Tutorial
38/101
38
Part III
AspectJ IDE support
programming environment
AJDE support for emacs, JBuilder 3.5, JBuilder 4, Forte 4J
also jdb style debugger (ajdb)
and window-based debugger
navigating AspectJ code
compiling
tracking errors debugging
ajdoc
8/11/2019 Aspectj Tutorial
39/101
39
Part IV
Using Aspects
where we have been
AspectJ mechanisms
Part II:
crosscutting in the code
mechanisms AspectJ provides
problem structure
Part IV:
crosscutting in the design, and
how to use AspectJ to capture that
and where we are going
8/11/2019 Aspectj Tutorial
40/101
40
goals of this chapter
present examples of aspects in design intuitions for identifying aspects
present implementations in AspectJ how the language support can help
work on implementations in AspectJ putting AspectJ into practice
raise some style issues
objects vs. aspects when are aspects appropriate?
example 1
plug tracing into the system
exposes join points and uses very simpleadvice
an unpluggable aspect
the programs functionality is unaffected by theaspect
uses both aspect and object
plug & play tracing
8/11/2019 Aspectj Tutorial
41/101
41
tracing without AspectJ
TraceSupport
class Point {voidset(int x, int y) {TraceSupport.traceEntry(Point.set);
_x = x; _y = y;TraceSupport.traceExit(Point.set);
}}
class TraceSupport {static int TRACELEVEL = 0;static protectedPrintStream stream = null;static protected int callDepth = -1;
static voidinit(PrintStream _s) {stream=_s;}
static voidtraceEntry(String str) {if (TRACELEVEL == 0) return;callDepth++;printEntering(str);
}
static voidtraceExit(String str) {if (TRACELEVEL == 0) return;callDepth--;printExiting (str);
}
}
a clear crosscutting structure
all modules of the system use thetrace facility in a consistent way:
entering the methods andexiting the methods
this line is aboutinteracting withthe trace facility
TraceSupport
8/11/2019 Aspectj Tutorial
42/101
42
tracing as an aspect
aspectMyClassTracing {
pointcutpoints():within(com.bigboxco.boxes.*) &&executions(* *(..));
before(): points() {TraceSupport.traceEntry(
tjp.className + . + tjp.methodName);}after(): points() {TraceSupport.traceExit(
tjp.className + . + tjp.methodName);}
}
TraceSupport
plug in:
unplug:
or
plug and debug
ajc Point.java Line.java
ajc Point.java Line.javaTraceSupport.java MyClassTracing.java
8/11/2019 Aspectj Tutorial
43/101
43
plug and debug
//From ContextManager
publicvo idservice( Request rrequest, Responserresponse ) {// log( "New request " + rrequest) ;try {
// System.out.print("A");rrequest.setContextManager( this );rrequest.setResponse(rr espons e);rresponse.setRequest(rrequest );
// wront request - parsing errorint statu s=rresponse.getSta tus();
if( status < 400 )status=processRequest( rrequest );
if(status==0)status=authenticate( rrequest, rresponse );
if(status == 0)status=authorize( rrequest, rresponse );
if( status == 0 ) {rrequest .getWrappe r().handleRequest(rrequest ,
rresponse);} else {
// something went wronghandleError( rrequest, rresponse, null, status );
}} catch (Throwable t) {
handleError( rrequest, rresponse, t, 0 );}// System.out.print("B");try {
rresponse.finish();rrequest.recycle();rresponse.recycle();
} catch ( Throwable ex ) {if(debug>0) log( "Error closing request " + ex);
}// log( "Done with request " + rrequest );// System.out.print("C");return;}
// log( "New request " + rrequest );
// System.out.print(A);
// System.out.print("B");
// log("Done with request " + rrequest);
if(debug>0)
log("Error closing request " + ex);
// System.out.print("C");
plug and debug
turn debugging on/off without editingclasses
debugging disabled with no runtimecost
can save debugging code betweenuses
can be used for profiling, logging easy to be sure it is off
8/11/2019 Aspectj Tutorial
44/101
44
aspects in the design
objects are no longer responsible for usingthe trace facility trace aspect encapsulates that responsibility, for
appropriate objects
if the Trace interface changes, that change isshielded from the objects only the trace aspect is affected
removing tracing from the design is trivial just remove the trace aspect
have these benefits
aspects in the code
object code contains no calls to tracefunctions trace aspect code encapsulates those calls, for
appropriate objects
if the trace interface changes, there is noneed to modify the object classes only the trace aspect class needs to be modified
removing tracing from the application istrivial compile without the trace aspect class
have these benefits
8/11/2019 Aspectj Tutorial
45/101
45
tracing: object vs. aspect
using an objectcaptures tracingsupport, but doesnot capture itsconsistent usage byother objects
using an aspectcaptures theconsistent usage ofthe tracing supportby the objects
TraceSupport TraceSupport
tracing
Make the tracing aspect a library aspectby using an abstract pointcut.
The after advice used runs whether thepoints returned normally or threwexceptions, but the exception thrown isnot traced. Add advice to do so.
exercises
8/11/2019 Aspectj Tutorial
46/101
46
exercise
aspect TracingXXX {// what goes here?
}
aspect TraceMyClasses extends TracingXXX {// what goes here?
}
refactor TraceMyClasses into a reusable
(library) aspect and an extension
equivalent to TraceMyClasses
exercise
abstract aspect TracingProtocol {
abstractpointcut tracePoints();
before(): points() {Trace.traceEntry(tjp.className + . + tjp.methodName);
}after(): points() {Trace.traceExit(tjp.className + . + tjp.methodName);
}}
aspect TraceMyClasses extends TracingProtocol {
pointcut points():within(com.bigboxco.boxes.*) &&executions(* *(..));
}
we now have the Trace class, and two
aspects, from a design perspective,
what does each implement?
8/11/2019 Aspectj Tutorial
47/101
47
example 2
Point
x: double
y: doubletheta: double
rho: double
rotate(angle:double)
offset(dx:double,dy:double)...
CloneablePoint
clone()
ComparablePoint
compareTo(o:Object)
HashablePoint
equals(o:Object)
hashCode()
roles/views
CloneablePoint
aspect CloneablePoint {
Point +implements Cloneable;
public Object Point.clone() throws CloneNotSupportedException {// we choose to bring all fields up to date before cloning
makeRectangular(); // defined in class PointmakePolar(); // defined in class Pointreturn super.clone();
}}
8/11/2019 Aspectj Tutorial
48/101
48
roles/views
Write the HashablePoint andComparablePoint aspects.
Consider a more complex system.Would you want the HashablePointaspect associated with the Point class,or with other HashableX objects, orboth?
Compare using aspects for role/view
abstraction with other techniques orpatterns.
exercises
example 3
interface OutputStream {public voidwrite(byte b);public voidwrite(byte[] b);
}
/*** This SIMPLE aspect keeps a global count of all* all the bytes ever written to an OutputStream.*/aspect ByteCounting {
int count = 0;
int getCount() { return count; }
// //// what goes here? //// //
}
counting bytes
8/11/2019 Aspectj Tutorial
49/101
49
exercise complete the codefor ByteCounting
/*** This SIMPLE aspect keeps a global count of all* all the bytes ever written to an OutputStream.*/aspect ByteCounting {
int count = 0;int getCount() { return count; }
}
counting bytes v1
aspect ByteCounting {
int count = 0;int getCount() { return count; }
after():receptions(voidOutputStream.write(byte)) {
count = count + 1;}
after(byte[] bytes):receptions(voidOutputStream.write(bytes)) {
count = count + bytes.length;}
}
a first attempt
8/11/2019 Aspectj Tutorial
50/101
50
counting bytes
class SimpleOutputStreamimplements OutputStream {public voidwrite(byteb) { }
public voidwrite(byte[] b) {for (int i = 0; i < b.length; i++) write(b[i]);
}}
class OneOutputStreamimplements OutputStream {public voidwrite(byteb) {..}
public voidwrite(byte[] b) {..}}
some stream implementations
counting bytes
class OtherOutputStreamimplements OutputStream {public voidwrite(byteb) {
byte[] bs = new byte[1];bs[0] = b;write(bs);
}
public voidwrite(byte[] b) { }}
another implementation
8/11/2019 Aspectj Tutorial
51/101
51
counting bytes v2
aspect ByteCounting {
int count = 0;
int getCount() { return count; }
pointcut allWrites(): receptions(voidOutputStream.write(byte)) ||receptions(voidOutputStream.write(byte[]));
pointcutwithinWrite(): cflow(allWrites());
after():!withinWrite() && receptions(voidOutputStream .write(byte)) {
count++;}
after(byte[] bytes):
!withinWrite() && receptions(voidOutputStream .write(bytes)) {count = count + bytes.length;}
}
using cflow for more robust counting
counting bytes v3
aspect ByteCounting of eachobject(allWrites()) {int count;
int getCountOf(OutputStream str) {return ByteCounting.aspectOf(str).count;
}
... count++;
... count += bytes.length;
}
per-stream counting
8/11/2019 Aspectj Tutorial
52/101
52
counting bytes
How would you count bytes writtenover this interface without aspects?
How do the aspects change if themethod voidwrite(Collection c) isadded to the OutputStream interface?
Consider a system in which you wrotenot only bytes, but byte generators(Objects with a run() method that may
output its own bytes). How would youneed to change v2?
exercises
example 4
workers need to know the caller:
capabilities
charge backs to customize result
caller1
caller2
Service
worker 1 worker 3worker 2
context-passing aspects
8/11/2019 Aspectj Tutorial
53/101
8/11/2019 Aspectj Tutorial
54/101
8/11/2019 Aspectj Tutorial
55/101
55
abstract aspect CapabilityChecking {
pointcut invocations(Caller c):instanceof(c) && calls(void Service.doService(String));
pointcut workPoints(Worker w):receptions(void w.doTask(Task));
pointcut perCallerWork(Caller c, Worker w):cflow(invocations(c)) && workPoints(w);
before (Caller c, Worker w): perCallerWork(c, w) {
w.checkCapabilities(c);}
}
context-passing aspects
context-passing aspects
The before advice on theperCallerWork pointcut calls the
workers checkCapabilities methodto check the capabilities of the caller.What would be an appropriate way towrite that method?
exercises
8/11/2019 Aspectj Tutorial
56/101
56
example 5properties of interfaces
interface Forest {
int howManyTrees();
int howManyBirds();
...
}
pointcut forestReceptions():receptions(* Forest.*(..));
before(): forestReceptions(): {
}
aspects on interfaces
aspect Forestry {
pointcut ForestMethodReceptions():
receptions(* Forest.*(..));
before(): ForestMethodReceptions() {
System.out.println(thisJoinPoint.methodName +
" is a Forest-method.");
}
}
a first attempt
8/11/2019 Aspectj Tutorial
57/101
8/11/2019 Aspectj Tutorial
58/101
58
aspects on interfaces
In this example you needed toconstrain a pointcut because ofundesired inheritance. Think of anexample where you would want tocapture methods in a super-interface.
Constraining a pointcut in this way canbe seen as an aspect id iom. What otheridioms have you seen in this tutorial?
exercises
example 6
client reactions to failures:
- abort- try another server
RMI exception aspects
8/11/2019 Aspectj Tutorial
59/101
59
a TimeServer design
the TimeService
public interface TimeService extends Remote {
/*** What's the time?*/
public Date getTime() throws RemoteException;
/*** Get the name of the server*/
public String getName() throws RemoteException;
/*** Exported base name for the service
*/public static final String nameBase = "TimeService";}
8/11/2019 Aspectj Tutorial
60/101
60
the TimeServer
public class TimeServer extends UnicastRemoteObjectimplements TimeService {
/*** The remotely accessible methods
*/public Date getTime() throws RemoteException {return new Date();}public String getName() throws RemoteException {return toString();}/**
* Make a new server object and register it*/
public static voidmain(String[] args) {Time