java cglibでmixin - mixinってなんだろう。
2007/07/11
java
既に生成されたオブジェクトにたいして、あらたにマーカーインターフェイスを付加できたらいいなと考えました。それでCGLIBを使用した方法です。
参考:
cglib メモ
非常に参考になりました。
CGLIB
Code Generation Library - Code Generation Library
シナリオ:
既に生成されたオブジェクトにたいして、あらたにインターフェイスを付加する
package mixin;
import net.sf.cglib.proxy.Mixin;
public class Test {
public static void main(String[] args) {
new Test().testMixin();
}
void testMixin() {
C c = mixin(new A() {
@Override
public void a() {
System.out.println("o_o i am A!!");
}
});
/* もとの型を保持しているかチェック */
if (c instanceof A) {
((A) c).a();
}
c.c();
}
/*
* クラス配列とクラス配列を連結します。
*/
static Class[] concat(Class[] a, Class[] b) {
Class[] arr = new Class[a.length + b.length];
System.arraycopy(a, 0, arr, 0, a.length);
System.arraycopy(b, 0, arr, a.length, b.length);
return arr;
}
interface A {
public void a();
}
interface C {
public void c();
}
/*
* もとのオブジェクトにたいして、Cインターフェイスを付け加えます。
*/
public C mixin(Object o) {
Class[] interfaces = concat(new Class[] { C.class }, o.getClass()
.getInterfaces());
Object[] delegates = new Object[] { new C() {
@Override
public void c() {
System.out.println("i am C o_o!");
}
}, o };
Object obj = Mixin.create(interfaces, delegates);
C c = (C) obj;
return c;
}
}
import net.sf.cglib.proxy.Mixin;
public class Test {
public static void main(String[] args) {
new Test().testMixin();
}
void testMixin() {
C c = mixin(new A() {
@Override
public void a() {
System.out.println("o_o i am A!!");
}
});
/* もとの型を保持しているかチェック */
if (c instanceof A) {
((A) c).a();
}
c.c();
}
/*
* クラス配列とクラス配列を連結します。
*/
static Class[] concat(Class[] a, Class[] b) {
Class[] arr = new Class[a.length + b.length];
System.arraycopy(a, 0, arr, 0, a.length);
System.arraycopy(b, 0, arr, a.length, b.length);
return arr;
}
interface A {
public void a();
}
interface C {
public void c();
}
/*
* もとのオブジェクトにたいして、Cインターフェイスを付け加えます。
*/
public C mixin(Object o) {
Class[] interfaces = concat(new Class[] { C.class }, o.getClass()
.getInterfaces());
Object[] delegates = new Object[] { new C() {
@Override
public void c() {
System.out.println("i am C o_o!");
}
}, o };
Object obj = Mixin.create(interfaces, delegates);
C c = (C) obj;
return c;
}
}
ちなみに変な挙動する箇所を一箇所みつけたのですが、時間があるときに追求しようと思います。
というのは、
Object[] delegates = new Object[] { new C() {
@Override
public void c() {
System.out.println("i am C o_o!");
}
}, o };
のオブジェクトの配列を変えるだけで、
Exception in thread "main" java.lang.ClassCastException: mixin.Test$2 cannot be cast to mixin.Test$A
at mixin.Test$C$$MixinByCGLIB$$e894d247.a()
at mixin.Test.testMixin(Test.java:23)
at mixin.Test.main(Test.java:8)
at mixin.Test$C$$MixinByCGLIB$$e894d247.a(
at mixin.Test.testMixin(Test.java:23)
at mixin.Test.main(Test.java:8)
といった例外が発生してしまいます。
何故でしょうか?
: