書面で今日Spring
エージェントを導入する際に報告されたエラー:
Exception in thread "main" org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'inter1' is expected to be of type 'com.dengchengchao.springtest.intertest.Inter1Impl' but was actually of type 'com.sun.proxy.$Proxy14'
おそらくその型変換エラーを意味します。
次のようにソースコードは次のとおりです。
ApplicationContext ctx = new AnnotationConfigApplicationContext(Conf.class);
Inter1 inter1 = ctx.getBean("inter1", Inter1Impl.class);
inter1.say1();
Inter2 inter2=(Inter2) inter1;
inter2.say2();
その後、google
エージェントへの少しの方法が見つかりました。CGLIB
ラインを。
我々は、すべて知っているJDK
非エージェント・インターフェースのクラスのために、それが使用されるべきである、唯一のエージェントインターフェイスをCGLIB
。
のでCGLIB
、継承を通じてプロキシクラスを達成するために、およびJDK
インタフェースによって達成されます。
しかし、私はここにInter1
はっきりとインタフェースです。その後、ダブルチェックコードは、実際には、使用することを見つけJava
、プロキシが限り変化として、OKまた、次のコード行です。
Inter1 inter1 = ctx.getBean("inter1", Inter1.class);
言い換えれば、あるべき形に変換する必要があるInter1.class
と、特定のクラスにはできませんInter1Impl
。
なぜJava
プロキシのみサポートエージェントインターフェースは、ここで我々は焼き深い表情を来ります:
まず、インタフェースを定義します。
public interface People {
void eat();
}
そして、実装クラスを定義します。
public class Student implements People{
@Override
public void eat() {
System.out.println("用手吃");
}
}
私たちは、プロキシクラスを定義します。
public class StudentInvokeHandler implements InvocationHandler {
private Object target;
public StudentInvokeHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("饭前洗手");
Object retVal = method.invoke(target, args);
System.out.println("饭后吃水果");
return retVal;
}
}
コールへのプロキシ経由次に、Student
public static void main(String[] args) {
//初始化Student
Student student = new Student();
//初始化Student代理类
StudentInvokeHandler studentInvokeHandler = new StudentInvokeHandler(student);
//通过代理获取代理独享
People studentProxy = (People) Proxy.newProxyInstance(StudentInvokeHandler.class.getClassLoader(), new Class[]{People.class}, studentInvokeHandler);
//通过代理对象调用eat方法
studentProxy.eat();
}
見ることができ、Java
代理店は非常にシンプルですが、一番下には、それを達成する方法ですか?
参照すると、JDKの動的プロキシ実装原理を詳しく説明し、我々はmain
約設定JVM
プロパティ
public static void main(String[] args) {
//将生成的代理类文件保存
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
Student student = new Student();
StudentInvokeHandler studentInvokeHandler = new StudentInvokeHandler(student);
People studentProxy = (People) Proxy.newProxyInstance(StudentInvokeHandler.class.getClassLoader(), new Class[]{People.class}, studentInvokeHandler);
studentProxy.eat();
}
実行した後、プロジェクトはのルートディレクトリに見つけることができるcom/sun/proxy/$Proxy0.class
プロキシでファイル、Student
生成されたオブジェクト.class
ファイル:
public final class $Proxy0 extends Proxy implements People {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void eat() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("com.dengchengchao.springtest.proxy.People").getMethod("eat");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
上記のファイルを通して、私たちは見つけることができます:
生成されたプロキシクラスの継承
Proxy
を実現People
インターフェース理由はここにあり
JDK
、プロキシが唯一のプロキシインタフェースは、プロキシではない特定のクラスは、ためができJava
、複数のない継承、それが唯一のインターフェイスを実装することができますインターフェイスが達成されるので、このようにプロキシオブジェクトを生成します
proxy
proxy instanceof People //true proxy instanceof Student //false
これは、私たちが遭遇した問題の根本的な原因の始まりであるproxy
だけで達成するためPeople
のインタフェースから継承されていないStudent
あなたがすることはできませんので、クラスproxy
に反対しStudent
、それは障害を報告したタイプ。
問題を理解し、基盤となる将来の使用のJDK
プロキシクラスが、それは別のミスをすることはありません。
あなたはそれが良かったと思った場合は、懸念のマイクロチャネル公共数以下のQRコードをスキャンする歓迎:随時ヤットツアーのJava、Javaへの関連記事を公開し、毎日を進めた、注目のおかげで