--- /dev/null
+
+
+public @interface BussFacade {
+
+}
--- /dev/null
+
+
+
+
+@NeedsXYZ
+public class ClientCode
+{
+
+ MyInterface __Interface__ = null;
+
+ ClientProxy specialConfigProxy = new ClientProxy();
+
+
+ void doIt() {
+ System.out.println("hold onto your hat...");
+ System.out.println("the answer is:"+ __Interface__.doB(42)); // direct Call is intercepted here
+
+ System.out.println("and now, "
+ + specialConfigProxy.additionalValueServiceForTheCustomer()
+ ); // indirect call is intercepted in the proxy
+ }
+
+
+
+ public static void main(String[] args) {
+
+ new ClientCode().doIt();
+
+ }
+}
--- /dev/null
+
+
+public class ClientProxy extends MyServiceImpl
+{
+
+ // just for this demo here; this cast allows
+ // us to call to the interface (without the cast
+ // we'd get a class cast exception)
+ MyInterface this_in_disguise = this;
+
+
+ @Clientside
+ public String additionalValueServiceForTheCustomer() {
+ return "if you don't know what to ask, then you "
+ + this_in_disguise.doA(42); // call through to the server side
+ }
+
+}
--- /dev/null
+
+
+public @interface Clientside {
+
+
+}
--- /dev/null
+
+
+public @interface Factory {
+
+}
--- /dev/null
+
+
+
+// NOTE: the presence of this Aspect, together with ServiceCall.aj
+// seems to trigger the infinite loop on the second or third re-build.
+//
+// Sometimes it triggered even if the @NeedsXYZ isn't used at all
+
+public aspect FactoryMarker
+{
+
+ public interface BootSpringKontext { };
+
+ declare parents : @NeedsXYZ * implements BootSpringKontext;
+
+ public Object[] BootSpringKontext.loadXYZ() {
+ return new Object[] {"load it"};
+ }
+
+
+ declare @method : Object[] loadXYZ*() : @Factory;
+
+}
--- /dev/null
+
+@BussFacade
+public interface MyInterface
+{
+
+ String doA(int lo);
+
+ String doB(int lolo);
+
+}
--- /dev/null
+
+public class MyServiceImpl implements MyInterface
+{
+
+ public String doA(int lololo) {
+ System.out.println("really did it "+lololo);
+ return "really got it: "+lololo;
+ }
+
+
+ public String doB(int lala) {
+ return doA(lala);
+ }
+
+}
--- /dev/null
+
+public @interface NeedsXYZ {
+
+}
--- /dev/null
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.Signature;
+
+
+@Clientside
+public aspect ServiceCall
+{
+
+ public pointcut ServicePoint()
+ : call( * (@BussFacade *).*(..) )
+ && !@within(Clientside)
+ && !@annotation(Clientside)
+ && ( !@within(ServiceImplementation)
+ || @withincode(Clientside)
+ )
+ ;
+
+ declare @type
+ : hasmethod(* (@BussFacade *).*(..)) : @ServiceImplementation
+ ;
+
+ public @interface ServiceImplementation { }
+
+
+ private pointcut call_Service(Object businessFacade)
+ : ServicePoint()
+ && target(businessFacade);
+
+
+ protected Object findImpl(Object bussFacade, JoinPoint.StaticPart location)
+ {
+ Class dienstID;
+ if ( null!=bussFacade )
+ dienstID = bussFacade.getClass();
+ else {
+ Signature sig = location.getSignature();
+ dienstID = sig.getDeclaringType();
+ }
+ Object impl = new MyServiceImpl(); // call ServiceLocator here
+ return impl;
+ }
+
+
+
+ Object around(Object bussFacade)
+ : call_Service(bussFacade)
+ {
+ try {
+ Object umgelenkt = findImpl(bussFacade, thisJoinPointStaticPart);
+ Object res = proceed(umgelenkt);
+ return res;
+ }
+ catch(Throwable T) {
+ System.out.println("oh my");
+ throw new RuntimeException(T);
+ }
+ }
+
+}
--- /dev/null
+
+
+
+@NeedsXYZ
+public class YetAnotherClass
+{
+
+}
--- /dev/null
+
+public class MyServiceImpl implements MyInterface
+{
+
+ public String doA(int lololo) {
+ System.out.println("really did it "+lololo);
+ return "really got it: "+lololo;
+ }
+
+
+ public String doB(int lala) {
+ return doA(lala);
+ }
+
+}