Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] aspectj presentation

My story so far (TODO REFACTOR):
Introduction:

Recap, Object-Oriented Programming principles:

Objects should be loosly coupled to eachother or there location.
Classes should be specialists in one well defined functionality leaving 
any other functionality to other objects.
Functionality should be encapselled behind there interfaces.
Code should only be written once.

Conclusion well designed components are very good at solving isolated 
problems. 
But not when parts are spread across system while being mangled through other 
parts.

J2EE solves this partially with declarative programming. certain 
non-functionality logic 
is declared instead being mixed and repeated through the business logic.

e.g: method "a()" must be transactional.
     method "b()" may only be executed by a user in role "x".

But we are still stuck with the declarative semantics the J2EE Specification 
provides. 
There is no standard way to customise them. Components are very coupled to 
there context. the declarative aspect
of the system is not portable.

With aspect oriented programming (AOP) we have all these power under our 
fingertips because:
- you can tell when a certain method is called 
- when a field is written or read.
- add fields and methods to a class. 
- change the inheritances chain. (implement multiple inheritance).
- soften exceptions.
- inspect the controll flow at runtime(change the flow/data) and 
compile(generate an error) time.
- when some point of execution is triggered it's up to you to decide what todo 
next 
(e.g: omit the method call, do constrain checking, start a transaction, etc).

The points of execution where you can listen to are called "joinpoints".
Adding extra code to a class is called an "introduction".
Doing something when joinpoint is triggered is called an advise.


AspectJ:
Aspectj is to AOP what websphere for J2EE is. (it's a websphere event)

Aspectj can be applied on every class where you have control over.
TODO: explain compilation and weaving process.

The classes which are produced by the aspectj platform are for
the JVM a classes just like another.

The aspectj compiler is pretty mature at this moment.

TODO: one (short) liners of concepts.

So when to apply aspectj and where.

Informal details, History and resources.


Op maandag 16 februari 2004 17:21, schreef John M. Adams:
> Philip <philipvanbogaert@xxxxxxxxxx> writes:
> > Hi,
> >
> > Can anybody give me some good pointers for an aspectj presentation. I'm
> > more technical oriented any abstract or high level view is welcome.
>
> I'm giving an AOP presentation tomorrow using AspectJ for examples.
> My main point is that a certain constraint programming model can be
> implemented very succinctly and modularly using AspectJ.  Previously,
> we considered that Lisp/CLOS/MOP was the only language that could do
> this in a reasonable way.  The aforementioned constraint model is used
> in a very large Lisp application that plans activities for the Hubble
> Space Telescope.
>
> The high-level view of AOP/AspectJ is pretty easy to communicate and I
> think the available presentations do a reasonable job.  My audience is
> very technical.  I plan to walk them through portions of the
> programming manual before presenting my example.
>
> I also plan to use the BeanShell to give an interactive demonstration
> of how the code works.  This makes it easier to show different things
> without have to have several main scripts or a configurable main.
>
> Here's my code:
>
> /*
>  * constraint.java
>  */
> package cosi;
>
> import org.aspectj.lang.JoinPoint;
> import org.aspectj.lang.Signature;
> import java.util.*;
> import java.lang.reflect.*;
>
> public aspect constraint {
>
> 	static Stack pendingDeps = new Stack();
> 	static Stack readContext = new Stack();
>
> 	pointcut inConstraint() : execution(void trans.ModelObject+.c_* (..));
>
> 	pointcut readField() : get(* trans.ModelObject+.*)
> 		&& !get(* trans.ModelObject+.deps)
> 		&& if (!readContext.empty());
>
> 	pointcut writeField() : set(* trans.ModelObject+.*)
> 		&& !set(* trans.ModelObject+.deps);
>
> 	before() : inConstraint() {
> 		readContext.push(thisJoinPoint);
> 	}
> 	after() : inConstraint() {
> 		readContext.pop();
> 	}
>
> 	before() : readField() {
> 		/* Get the context of the object that is reading a field. */
> 		JoinPoint rctx = (JoinPoint) readContext.peek();
> 		trans.ModelObject reader = (trans.ModelObject) rctx.getThis();
> 		String readerMethod = rctx.getSignature().getName();
>
> 		/* Get the context of the object that owns the field. */
> 		trans.ModelObject target = (trans.ModelObject) thisJoinPoint.getThis();
> 		String field = thisJoinPoint.getSignature().getName();
>
> 		/* cosi.Entities do not track self access */
> 		if (reader != target) {
> 			System.out.println(
> 				reader + "." + readerMethod + " read " + target + "." + field);
> 			target.recordDependency(field, reader, readerMethod);
> 		}
> 	}
>
> 	after() : writeField() {
> 		/* Get the context of the object that owns the field. */
> 		trans.ModelObject target = (trans.ModelObject) thisJoinPoint.getTarget();
> 		String field = thisJoinPoint.getSignature().getName();
> 		System.out.println("write of " + target + "." + field);
> 		Stack fdeps = (Stack) target.deps.get(field);
> 		if (null != fdeps) {
> 			while(!fdeps.empty()) {
> 				pendingDeps.push(fdeps.pop());
> 			}
> 		}
> 	}
>
> 	static public void propagate() {
> 		System.out.println("Propagating...");
> 		Iterator itr = pendingDeps.iterator();
> 		while (!pendingDeps.empty()) {
> 			Dependency dep = (Dependency) pendingDeps.pop();
> 			try {
> 				Class _class = dep.obj.getClass();
> 				Method meth = _class.getMethod(dep.meth, null);
> 				meth.invoke(dep.obj, null);
> 			} catch (Exception e) {
> 				System.out.println("Dang.");
> 			}
> 		}
> 	}
>
> 	public static class Dependency {
> 		private Dependency() {
> 		}
> 		public Dependency(trans.ModelObject _obj, String _meth) {
> 			obj = _obj;
> 			meth = _meth;
> 		}
> 		public boolean equals(Dependency other) {
> 			return obj == other.obj && meth.equals(other.meth);
> 		}
> 		public trans.ModelObject obj;
> 		public String meth;
> 	}
>
> 	public HashMap trans.ModelObject.deps = new HashMap();
>
> 	public void trans.ModelObject.showDeps() {
> 		/* Print out the dependency table */
> 		Iterator itr = deps.keySet().iterator();
> 		while (itr.hasNext()) {
> 			String fieldName = (String) itr.next();
> 			System.out.println(fieldName);
> 			Stack depSet = (Stack) deps.get(fieldName);
> 			Iterator _itr = depSet.iterator();
> 			while (_itr.hasNext()) {
> 				Dependency invoc = (Dependency) _itr.next();
> 				System.out.println("  " + invoc.meth + "  " + invoc.obj);
> 			}
> 		}
> 	}
>
> 	private void trans.ModelObject.recordDependency(
> 		String field,
> 		trans.ModelObject obj,
> 		String meth) {
> 		Dependency newDep = new Dependency(obj, meth);
> 		Stack stack = (Stack) deps.get(field);
> 		if (null == stack) {
> 			stack = new Stack();
> 			deps.put(field, stack);
> 		}
> 		if (-1 == stack.search(newDep)) {
> 			stack.push(newDep);
> 		}
> 	}
>
> }
>
>
> /*
>  * Alignment.java
>  */
> package trans;
>
> public class Alignment implements ModelObject {
> 	public Alignment() {
> 		exp = new Exposure(1);
> 	}
> 	public void c_foo () {
> 		alTime += exp.f_getDuration();
> 	}
> 	public void m_foo () {
> 		exp.duration = 41;
> 	}
> 	public int alTime;
> 	public Exposure exp;
> }
>
>
> /*
>  * Exposure.java
>  */
> package trans;
>
> public class Exposure implements ModelObject {
> 	public Exposure() {
> 	}
> 	public Exposure(int _duration) {
> 		duration = _duration;
> 	}
> 	public int f_getDuration() {
> 		return duration;
> 	}
>
> 	public int duration;
> 	public int fooby = 11;
> }
>
> /*
>  * ModelObject.java
>  */
> package trans;
>
> /**
>  * @author jmadams
>  */
> public interface ModelObject {
>
> }
> aspect FaultHandler {
>
> 	private boolean Server.disabled = false;
>
> 	private void reportFault() {
> 		System.out.println("Failure! Please fix it.");
> 	}
>
> 	public static void fixServer(Server s) {
> 		s.disabled = false;
> 	}
>
> 	pointcut services(Server s) : target(s) && call(public * * (..));
>
> 	before(Server s) : services(s) {
> 		if (s.disabled)
> 			throw new DisabledException();
> 	}
>
> 	after(Server s) throwing(FaultException e) : services(s) {
> 		s.disabled = true;
> 		reportFault();
> 	}
> }
>
> And here's a Beanshell session that demonstrates:
>
> bsh % show();
> <true>
> bsh % addClassPath("cosi.jar");
> bsh % a = new trans.Alignment();
> <trans.Alignment@50a649>
> write of trans.Exposure@5d391d.fooby
> write of trans.Exposure@5d391d.duration
> write of trans.Alignment@xxxxxxxxxx
> bsh % a.c_foo();
> trans.Alignment@50a649.c_foo read trans.Exposure@5d391d.duration
> write of trans.Alignment@50a649.alTime
> bsh % a.exp.showDeps();
> duration
>   c_foo  trans.Alignment@50a649
> bsh % a.m_foo();
> write of trans.Exposure@5d391d.duration
> bsh % cosi.constraint.aspectOf().propagate();
> Propagating...
> trans.Alignment@50a649.c_foo read trans.Exposure@5d391d.duration
> write of trans.Alignment@50a649.alTime
> bsh % a.alTime;
> <42>
>
> (altime was initially 0)



Back to the top