06. december 2010 - 19:09Der er
2 kommentarer og 1 løsning
cglib field access
Hi,
har en klasse Test
public class Test { private String value;
public Test() { value = "foo"; }
public void doSomething() { // ... } }
nu kan jeg skrive en interceptor, som kaldes, når en method bliver invoked.
Enhancer e = new Enhancer(); e.setSuperclass(Test.class); MethodInterceptor mi = new TestMethodInterceptor(); e.setCallback(mi);
Object o = e.create(); Test t = (Test)o;
Nu vil jeg gerne have access på class-member value:
public class TestMethodInterceptor { @Override public Object intercept(Object o, Method m, Object[] params, MethodProxy mp) { Class oClass = o.getClass(); Field f = o.getField("value"); f.setAccessible(true); f.set(o, "bar"); }
problemet er, at oClass er en proxy-class. Det er ikke Test.class. Så hvordan kan jeg få ovenstående code til at virke?
Proxy klassen extender faktisk den originale klasse, så problemet er ikke at value field ikke eksisterer men at getField metode kun returnerer public fields, men så er det til alt helt en getDeclaredField metode som returnerer alle slags fields - den kræver så at man eksplicit finder super klassen, men det er jo også muligt.
public class Test { private String value; public Test() { value = "foo"; } public void doSomething() { System.out.println(value); } public static void main(String[] args) { Test o = new Test(); o.doSomething(); Enhancer e = new Enhancer(); e.setSuperclass(Test.class); e.setCallback(new MethodInterceptor() { public Object intercept(Object o, Method m, Object[] params, MethodProxy mp) { try { Class<?> clz = o.getClass(); Field f = clz.getSuperclass().getDeclaredField("value"); f.setAccessible(true); f.set(o, "bar"); return mp.invokeSuper(o, params); } catch (Throwable e) { e.printStackTrace(); return null; } } }); Test o2 = (Test) e.create(); o2.doSomething(); } }
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.