**** インターフェースの定義
public interface Planet{
public void see();
}
**** 抽象クラスの定義
public abstract class AbstractPlanet implements Planet{
/* (非 Javadoc)
* @see Planet#see()
*/
@Prefunction("pre")
@Aftfunction("aft")
public void see(){
System.out.println("AbstractPlanet#see()");
}
public boolean pre(){
System.out.println("AbstractPlanet#pre()");
return true;
}
public boolean aft(){
System.out.println("AbstractPlanet#aft()");
return true;
}
}
**** 前処理アノテーション @Aftfunctionも同様
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Prefunction{
String value();
}
**** プロキシされるクラスのインターフェース
public interface Neptune extends Planet{
public void foo(String s);
}
**** Neptuneの実装 and AbstractPlanetの具象
class NeptuneImpl extends AbstractPlanet implements Neptune{
@DefSatellite private String satellite;
/*
* @see Neptune#foo(java.lang.String)
*/
@Prefunction("pre")
@Aftfunction("aft")
public void foo(String s){
System.out.println("Neptune#foo() s="+s);
System.out.println("Neptune#satellite="+satellite);
}
}
**** Field に付けるアノテーション
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DefSatellite{
}
**** プロキシ
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class PlanetProxy implements InvocationHandler{
private Object target;
private PlanetProxy(Planet obj){
this.target = obj;
}
public final static Object create(Planet obj){
return Proxy.newProxyInstance(obj.getClass().getClassLoader()
,obj.getClass().getInterfaces()
,new PlanetProxy(obj));
}
public final static Neptune createNeptune(){
Planet obj = new NeptuneImpl();
return (Neptune)Proxy.newProxyInstance(obj.getClass().getClassLoader()
,obj.getClass().getInterfaces()
,new PlanetProxy(obj));
}
/*
* @see java.lang.reflect.InvocationHandler
* #invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object)
*/
public Object invoke(Object proxy,Method m,Object args) throws Throwable{
if (proxy==null){throw new IllegalArgumentException("proxy is null");}
Field satelliteField = null; // satellie変数 Field
Field[] fls = this.target.getClass().getDeclaredFields();
for(int i=0;i < fls.length;i++){
if (fls[i].getAnnotation(DefSatellite.class)!=null){
satelliteField = fls[i];
break;
}
}
if (satelliteField != null){
// satellie変数 Field に値をセット
satelliteField.setAccessible(true);
satelliteField.set(this.target,"satellite_Moon");
}
Method targetMethod = this.target.getClass()
.getMethod(m.getName(),m.getParameterTypes());
try{
Prefunction pre = targetMethod.getAnnotation(Prefunction.class);
if (pre != null){
System.out.println("■ pre");
Method mt = this.target.getClass().getMethod(pre.value());
if (((Boolean)mt.invoke(this.target)).booleanValue()){
return m.invoke(this.target,args);
}
}else{
return m.invoke(this.target,args);
}
return null;
}finally{
Aftfunction aft = targetMethod.getAnnotation(Aftfunction.class);
if (aft != null){
System.out.println("■ after");
Method mt = this.target.getClass().getMethod(aft.value());
mt.invoke(this.target);
}
}
}
}
**** 呼び出し実行
Neptune pl = PlanetProxy.createNeptune();
pl.foo("test");
pl.see();