プログラマメモ2 - programmer no memo2

java cglibでmixin - mixinってなんだろう。 2007/07/11

既に生成されたオブジェクトにたいして、あらたにマーカーインターフェイスを付加できたらいいなと考えました。それで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;
}
}


ちなみに変な挙動する箇所を一箇所みつけたのですが、時間があるときに追求しようと思います。
というのは、

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)

といった例外が発生してしまいます。

何故でしょうか?

: