Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Aspect Oriented Programming in Java WITHOUT AspectJ?

Tags:

java

aop

ok this question's never been asked before on the web so here goes: I'm learning Java (beginner-intermediate level) and I decided to go ahead of class programme by trying out Aspect-Oriented programming.

Now this thing's supposed to be easy to learn (at least that's the web consensus) so much so that the "aspects" are said to be slightly modified versions of the standard classes, so my question is: if aspects are basically classes,

WHY do we have to install AspectJ to do AOP in Java?

as that just adds an extra layer of complexity making the concept even harder to grasp.

What I want is to be able to write an aspect without using AspectJ (or any other add-on), in other words I wanna do AOP using only BASIC Java & its standard java classes. is it possible and if so, how must I write these classes?

like image 783
user3578836 Avatar asked Apr 27 '14 18:04

user3578836


2 Answers

AspectJ is a, for lack of a better word, "pure" Aspect framework. The criteria being that it can be used widely in all sorts of circumstances. Any aspect, on any class, at any time.

That said, the aspect technique of intercepting and wrapping method calls, has found its way pervasively in Java. However, these trend towards specialization of the generic aspect concept for specific purposes.

A very early "aspect" was done with the early EJB capabilities. This entailed the use of XML files to augment classes and interfaces, so that the container could create proxy objects that would wrap method invocations in to transaction contexts. This wrapping of the methods is an aspect concept, but the early EJB spec only offered the capability on the very specific use case of transaction management.

The arrival of annotations with Java 1.5 opened up this augmentation concept of aspect oriented programming. It's not that you need annotations to enable this, rather it just makes the frameworks much easier to use, as the annotations eliminate the external meta data configuration (using, perhaps, XML files).

So, now, many Java systems use concepts from aspect oriented programming, typically through reflection and annotations, to implement certain capabilities. Whether this is instance injection, around methods, validation, etc.

The key component to it all is some mechanism to intercept the method call. AspectJ worked by changing the destination class on the fly, rather than interjecting a middle man. EJB works by creating proxies on interfaces (something you can do out of the box in Java), and then when a program asks the container for a instance, it provides a proxy backed by the actual instance.

So, to enable "generic" AOP, everywhere, all the time, you certainly need something wide ranging like AspectJ. But to get much of the benefits of it, you don't need to go that far. A simple Factory class and an Interface can do the job readily.

like image 153
Will Hartung Avatar answered Oct 07 '22 05:10

Will Hartung


Java does not support AOP out of the box and I would not recommend implementing it on your own because you will have to modify class files while they get loaded. Alternatively, you could also modify the complied class files, but that would be even more complicated.

AspectJ uses a Java Agent to setup the weaving class loader (which modifies the class files on load), but you could also use your own class loader manually. If your classes, which you want to modify, all implement an interface, then you can use Java Proxies for AOP. Otherwise you will have to use an external library like CGLib, Javassist or ASM (or learn how Java bytecode works).

Some further information:

  • How to use Java Proxies: http://java.dzone.com/articles/power-proxies-java
  • Bytecode generation libraries: Are there alternatives to cglib?
  • Java bytecode: https://en.wikipedia.org/wiki/Java_bytecode

Proxy example:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyExample {

    public static void main(String[] args) {
        AnInterface obj = new AClass();
        AnInterface proxyObj = createProxy(obj);
        System.out.println(obj.aMethod());
        System.out.println(proxyObj.aMethod());
    }

    private static AnInterface createProxy(AnInterface obj) {
        return (AnInterface) Proxy.newProxyInstance(ProxyExample.class.getClassLoader(),
                new Class<?>[] {AnInterface.class},
                new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return "proxy: " + method.invoke(obj);
            }
        });
    }

    static interface AnInterface {
        public String aMethod();
    }

    static class AClass implements AnInterface {
        @Override
        public String aMethod() {
            return "string";
        }
    }

}
like image 26
Joel Avatar answered Oct 07 '22 06:10

Joel