Call a method any time other methods are called
Sure you can do this, not with standard java but with AspectJ
Here is a simple example:
Aspect with an after-advice
package net.fsa.aspectj.test;
public aspect SuperMethdAspect {
pointcut afterPointCut() : execution(public * com.my.pack.age.MyClass.*(..));
after() : afterPointCut() {
System.out.println("Super");
}
}
You target class
package com.my.pack.age;
public class MyClass {
public void onStart() {
System.out.println("Start");
}
public void onEnd() {
System.out.println("End");
}
}
And finally some test app
package net.fsa.aspectj.test;
import com.my.pack.age.MyClass;
public class MyApp {
public static void main(String... args) {
MyClass myClass = new MyClass();
myClass.onStart();
myClass.onEnd();
}
}
Output
Start
Super
End
Super
Here is an implementation in pure Java using the Proxy class:
import java.lang.reflect.*;
import java.util.*;
public class Demo
{
public static void main(String[] args)
{
Map<String, String> map = new HashMap<String, String>();
map.put("onStart", "abc");
map.put("onEnd", "def");
Library library = new LibraryProxy(map, new LibraryImpl()).proxy();
library.onStart();
library.onEnd();
library.onRun();
}
}
interface Library
{
void onStart();
void onEnd();
void onRun();
}
class LibraryImpl
{
public void abc() { System.out.println("Start"); }
public void def() { System.out.println("End"); }
}
class LibraryProxy implements InvocationHandler
{
Map<String, String> map;
Object impl;
public LibraryProxy(Map<String, String> map, Object impl)
{
this.map = map;
this.impl = impl;
}
public Library proxy()
{
return (Library) Proxy.newProxyInstance(Library.class.getClassLoader(),
new Class[] { Library.class }, this);
}
@Override
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
{
Object res = null;
String name = map.get(m.getName());
if (name == null) {
System.out.println("[" + m.getName() + " is not defined]");
} else {
m = impl.getClass().getMethod(name, m.getParameterTypes());
res = m.invoke(impl, args);
}
System.out.println("super duper");
return res;
}
}
Output:
Start
super duper
End
super duper
[onRun is not defined]
super duper
Java doesn't really allow magic like this. In order for a call to happen, it has to appear within your (compiled) code. So the answer is no, not without explicitly adding a call to the relevant methods. However, you can hide that somewhat by using a preprocessor or runtime code generation.
I think AspectJ might be what you want.