Avatar billede kernelx Juniormester
06. december 2010 - 19:09 Der 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?

Mange tak allerede i forvejen!
Avatar billede arne_v Ekspert
07. december 2010 - 03:28 #1
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.

Nok snik snak - demo:

package december;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

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();
    }
}
Avatar billede kernelx Juniormester
07. december 2010 - 09:39 #2
super mange tak ... igen og igen!!! :-)
husk at skrive et eller andet som svar
Avatar billede arne_v Ekspert
07. december 2010 - 14:22 #3
svar
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester