I'm trying to add functionality into an interface method signature by using annotations.
the idea is to invoke some another methods fore each annotated one.
for example if I have this method signature:
public interface IMyInterface{
@Entity(visibileName = "Name")
public TextField getName();
}
I need to invoke a method that print the string name before, after this method. also if their is any way to define a functionality to this method on run time.
I'm also opened to structural changes.
If what you want is annotating interface
methods, than it is possible without AOP.
Just use Dynamic Proxies!
The base interface
to implement a proxy is InvocationHandler
InvocationHandler is the interface implemented by the invocation handler of a proxy instance.
Follow in-code comments.
static class MyInterfaceProxy implements InvocationHandler {
private static final Map<String, Method> METHODS = new HashMap<>(16);
static {
// Scan each interface method for the specific annotation
// and save each compatible method
for (final Method m : IMyInterface.class.getDeclaredMethods()) {
if (m.getAnnotation(YourAnnotation.class) != null) {
METHODS.put(m.getName(), m);
}
}
}
private final IMyInterface toBeProxied;
private MyInterfaceProxy(final IMyInterface toBeProxied) {
// Accept the real implementation to be proxied
this.toBeProxied = toBeProxied;
}
@Override
public Object invoke(
final Object proxy,
final Method method,
final Object[] args) throws InvocationTargetException, IllegalAccessException {
// A method on MyInterface has been called!
// Check if we need to call it directly or if we need to
// execute something else before!
final Method found = METHODS.get(method.getName());
if (found != null) {
// The method exist in our to-be-proxied list
// Execute something and the call it
// ... some other things
System.out.println("Something else");
}
// Invoke original method
return method.invoke(toBeProxied, args);
}
}
To use this InvocationHandler
implementation you need a real instance of the object to be proxied.
Say you have a Factory for MyInterface
implementations
MyInterface getMyInsterface() {
...
final MyInterface instance = ...
// Create the proxy and inject the real implementation
final IMyInterface proxy = (IMyInterface) Proxy.newProxyInstance(
MyInterfaceProxy.class.getClassLoader(),
new Class[] {IMyInterface.class},
new MyInterfaceProxy(instance) // Inject the real instance
);
// Return the proxy!
return proxy;
}