This document gives a quick reference overview of the JAsCo language. It is recommended to at least read the language reference partially to understand the general concepts and ideas before using this quick reference. For an in-depth explanation of every feature, see the language reference document as well.
See the table on the right for a full table of contents.
Contain one or more hooks that define crosscutting behavior in an independent way.
class Logger { hook LogHook { LogHook(method1(..args)) { execution(method2); } before() { log("EXECUTING: "+thisJoinPoint.getSignature()); } }
Additional triggering condition in full Java, returns a boolean. Is equivalent to if pointcut in AspectJ.
isApplicable() { return isEnabled; }
hook securityHook { ... public refinable Object noAccessPolicy(); ... }
hook securityHook { ... public refinable void noAccessPolicy() { throw new NoAccessException(thisJoinPoint); } ... }
Deploys aspect beans onto concrete context.
static connector LogDeployer { Logger.LogHook logaspect = new Logger.LogHook(void test.mymethod()); }
static connector PerThreadConnector { //predefined factory instantiation perthread Protocol.ProtocolChecker aspect3 = new Protocol.ProtocolChecker(....); //custom factory instantiation per(TypeOfMyFactory) Protocol.ProtocolChecker aspect5 = new Protocol.ProtocolChecker(....); }
Predefined Aspect Factories:
Custom Aspect Factories: They have to implement the jasco.runtime.aspect.factory.IAspectFactory interface. This interface contains one method, getAspectInstance, that is responsible for fetching the aspect instance for the currently executing joinpoint jp. The second argument allows to create a new hook instance and initialize it properly as defined in the associated connector.
public interface IAspectFactory { public IHook getAspectInstance(MethodJoinpoint jp, IAspectInstanceCreator creator); }
The following code fragment illustrates a custom aspect factory that returns a new hook instance for every class loader that loaded the executing class of the current joinpoint. As such, both the hook and the joinpoint are loaded by the same class loader and thus avoiding possible class loader hell problems.
package test.aspects; public class PerClassLoaderAspectFactory implements IAspectFactory { public PerClassLoaderAspectFactory(){} private Hashtable map = new Hashtable(); IHook getAspectInstance(MethodJoinpoint jp, IAspectInstanceCreator creator) { IHook instance = (IHook) map.get(jp.getClassLoader()); if(instance==null) { instance = creator.createNewInstance(jp.getClassLoader()); map.put(jp.getClassLoader(),instance); } return instance; } }
Good to know:
Per default, aspect beans are instantiated implicitly using the default constructor. It is also possible to explicitly instantiate the global aspect bean instance for each connector as follows:
class Test { public Test(String var) {} hook testHook { ... } } connector TestConnector { Test test = new Test("a custom string"); Test.testHook hookInstance = new Test.testHook(* *.*(*)); }
Good to know:
static connector LogDeployer { Logger.LogHook lmyloginst = new Logger.LogHook(void test.mymethod()); lmyloginst.before(); }
static connector LogDeployer { Test.TestAspect aspect1 = new Test.TestAspect(void test.mymethod()); Security.AccessControl aspect2 = new Security.AccessControl(void test.mymethod()); aspect1. before(); aspect2. before(); aspect2. around(); aspect1. around(); }
static connector LogDeployer { Logger.LogHook mylogger = new Logger.LogHook(void test.mymethod()); mylogger.setLogString("boepsiewoepsie"); }
static connector AccessControlDeployer { Security.AccessControl test = new Security.AccessControl(void test.mymethod()) { public refinable void noAccessPolicy() { System.errorAccess(thisHook.getUser(),thisJoinPoint,thisJoinPointObject); } }; }
Connector c = Connector.MyConnectorName.getConnector();
Connector.MyConnectorName.getConnector().myAspectVariableName(); //myAspectVariableName is the var name of the aspect instance in the connector, //e.g. aspect2 in the connector above
Connector.MyConnectorName.getConnector().myAspectVariableName(keyForPerInstantiation); //myAspectVariableName is the var name of the aspect instance in the connector, //e.g. aspect2 in the connector above //keyForPerInstantiation is the key to fetch the hook instance, //e.g. target object in case of perobject, targetclass in case of perclass etc...
Implements refinable methods in a type specific manner, the type after the refining token refers to the type of a hook and the type after the for token refers to the type of target objects (i.e. thisJoinPointObject) where this refinement is valid for. Use Object to define a global refinement.
The most specific refinement for a certain method is executed, inline refinements in the connector always have precedence over refining classes.
class TestRefinement2 refining TestAspect.TestHook for status.DataStore { public refinable Object getData() { //refinable modifier here as well DataStore store = thisJoinPointObject; thisHook.iAmRefining(thisJoinPoint.getName()); return store.getData(); } }
class TestRefinement2 refining TestAspect.TestHook for java.io.Serializable
Virtual mixins allow to insert the implementation of an interface in target classes so that other aspects can depend on that. This is mainly useful for communicating information between aspects.
In order to cast an object to the mixin interface, use the following code:
//customer is an instance of Customer where the ICustomerInfo mixin //has been inserted as described below ICustomerInfo info = (ICustomerInfo) customer;
The ICustomerInfo interface consists of:
interface ICustomerInfo extends jasco.runtime.mixin.IMixin { public boolean isFrequent(); public boolean setIsFrequent(boolean b); }
The interface is inserted into a target class by simply declaring a hook that implements the interface and correspondig connector. Notice the perobject modifier in the connector for having one hook instance per customer instance. Otherwise the isFrequent property would be global for all customer instances.
The hook is also able to define regular advices. Those are executed as usual, i.e. for all method executions on customer objects in this case.
class BRFrequent { hook Introduce implements ICustomerInfo { private boolean isFrequent=false; Introduce(void method(..args)) { execution(method(args)); } public boolean isFrequent() { return isFrequent ; } public boolean setIsFrequent(boolean b) { isFrequent=b; } } }
static connector IntroduceMixin { perobject BRFrequent.Introduce hook1 = new BRFrequent.Introduce(* Customer.*(*)); //the wildcards are important! }
Now other hooks are able to access this mixin through the following code. Note that the customer variable is an instance of the Customer class.
around returning(double price) { ICustomerInfo mixin = (ICustomerInfo) customer; if(mixin.isFrequent()) return applyDiscount(price); else return price; }
Good to know:
Combination Strategies are able to manage the cooperation of aspects.
class ExcludeCombinationStrategy implements CombinationStrategy { private Object hookA, hookB; ExcludeCombinationStrategy(Object a,Object b) { hookA = a; hookB = b; } HookList validateCombinations(Hooklist hlist) { if (hlist.contains(hookA)) hlist.remove(hookB); return hlist; } }
static connector DiscountConnector { Discounts.BirthdayDiscount birthday = ... Discounts.FrequentDiscount frequent= ... addCombinationStrategy(new ExcludeCombinationStrategy(frequent, birthday)); }
TODO, refer to the tutorial and papers for now.
In order to exclude classes from JAsCo weaving, one has to either list them as a jvm launch option or supply an annotation in the source code. JAsCo supports an annotation that can be placed on all java elements to exclude it from weaving:
jasco.runtime.annotation.NoJAsCoAOP
e.g. when supplying a class X with this annotation, JAsCo will never touch it.
e.g. when supploying method y of class X with is annotation, JAsCo will never touch method y, but might weave other methods of class X