• [ << ]
  • [ 0 ]
  • [ 1 ]
  • [ 2 ]
  • [ 3 ]
  • [ >> ]
Jun '04
28

Doe het zelf : Aspect Oriented Frameworks


Het gebruik van Aspect Oriented Programming (AOP) is al geruime tijd mogelijk, maar pas recent populair geworden. De voordelen van AOP zijn overduidelijk : de mogelijkheid om in code onderscheid te maken tussen probleem gebieden die met elkaar verweven zijn. Technisch (logging, transacties, security) maar vooral ook in het business domein. De frameworks/taalextensies die er zijn werken goed maar zijn soms ondoorzichtig in hun werking. Om inzicht te verkrijgen over hoe deze frameworks tewerk gaan, bouwen we in dit artikel een eenvoudig AOP framework in standaard Java.

Download de Source code

AOP ? Wat is dat eigenlijk ?

Grof gezegd is AOP de ultieme Hacker Tool. Natuurlijk zullen wij AOP zo niet gebruiken, maar de mogelijkheden zijn er zeker :-) Namelijk : AOP stelt je in staat buiten de object definitie om modificaties te maken op het gedrag van het object.

Het introduceert een aantal nieuwe termen :
  • Pointcut : geeft aan welke methoden nieuw of ander gedrag moeten krijgen.
  • Advice : het andere gedrag. Dit gedrag kan plaats vinden voor, na of in plaats van het oude gedrag.
  • Introduction: Het toevoegen van interfaces en implementaties aan een bestaand object.
Stel we hebben de volgende klasse :
                 
 public class Fordo {
 	public void disposeOfThing() {
 	 throw new RuntimeException("I Cannot! Its too precious.");
 	}
 }

                
Je zou dan een Pointcut kunnen specificeren op de methode Fordo.disposeOfThing(). Als je logging zou willen toevoegen kan je before Advice gebruiken dat een regel logt naar de Logger -> "Fordo tries to dispose of the Thing". Een voorbeeld van Introductie zou bijvoorbeeld het toekennen van de Serializable interface aan Fordo. Kunnen we later verder lezen :-)

Manieren om Aspects te realiseren

De dingen die in het vorige stuk beschreven staan kan je niet zomaar in Java realiseren zonder kunstgrepen. De bestaande frameworks gebruiken 3 verschillende strategie├źn om het Aspect Geori├źnteerde gedrag te bewerkstelligen :
  • Genereren en samenvoegen van Source Code (AspectJ)
  • Bytecode modificatie (AspectWerkz, JBoss-AOP)
  • Dynamic Proxies (Nanning)
AspectJ is een soort van preprocessor, voordat de Java Compiler gestart wordt, word eerst de source code van de objecten samengevoegd met de sourcecode/gegenereerde code van de Aspecten welke dan als geheel gecompileerd wordt. Als je de boel decompileert (met jad bijvoorbeeld) dan zul je zien dat als een methode een Advice heeft dit net voordat de methode wordt aangeroepen als een aparte methode aanroep wordt uitgevoerd.

Een typisch voorbeeld met before en after Advice :
                 
 Fordo halfling = new Fordo();	
 //
 try {
	//
	// Before advice.
	//
	AspectLogger.aspectOf().ajc$before$
		nl_cad_aop_AspectLogger$280(halfling);
	//
	// Actual Method invocation
	//
	theHalfling.disposeOfThing();
	//
 } catch(Throwable throwable) {
	//
	// After advice in case of Exception
	//
	AspectLogger.aspectOf().ajc$after$
		nl_cad_aop_AspectLogger$2fb(halfling);
	//
	// Re-Throw the exception.
	//
	throw throwable;
 }
 //
 // After advice if all goes well.
 //
 AspectLogger.aspectOf().ajc$after$
	nl_cad_aop_AspectLogger$2fb(halfling); 
 
                
Overal waar een methode wordt aangeroepen waarop een pointcut met advice gedefinieerd is wordt een soortgelijk blokje code toegevoegd in de source, met daarin referenties naar de methoden in het Aspect (nu een doodordinaire singleton). Je broncode mag dan puur en zuiver zijn, maar wat er onderwater van gemaakt wordt is net zo (of meer) smerig dan dat je het met de hand zou doen.

Met bytecode manipulatie werkt het ongeveer netzo, alleen dan in byte codes i.p.v source.

De laatste variant, die met dynamic proxies, pakt het anders aan. In plaats van extra method calls of byte codes toe te voegen wordt er hier een compleet object toegevoegd. Een object met exact dezelfde interface als het object dat wordt aangeroepen. Alleen met extra gedrag. Zoals bijvoorbeeld logging.

Aangezien deze laatste variant gewoon binnen Java gerealiseerd kan worden is dit de methode die in dit artikel gebruikt wordt, maar voordat we de wondere wereld van java.lang.reflect in duiken, kijken we eerst welk software pattern hieraan ten grondslag ligt.

  • [ << ]
  • [ 0 ]
  • [ 1 ]
  • [ 2 ]
  • [ 3 ]
  • [ >> ]