版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/telrob/article/details/83243363
Java中为我们提供了动态代理Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)方法用于代理某个类,但是有个缺点,该类必须继承某个接口,然后才能代理该类。
我们在使用spring 时候经常编写某个类,然后spring就可以直接代理,具体是如何 实现的呢?再次之前我们必须要了解一些技术框架,CGLib是什么,ASM,javassists又是什么,本文主要与后两者有关,就先简要介绍下吧,Java编译后的class文件时一种字节码文件,而ASM,javassists就可以通过代码动态生成字节码,那这样就能够做很多功能了,动态生成某个类或者接口等。
下面进入本文的主题,动态代理某个没有继承接口的类,下面是整体的步骤:
- 根据当前类通过反射生成对应的接口
- 在生成当前类的子类并继承第一步生成的接口
- 通过动态代理第一步接口
- 调用接口中的方法查看执行结果。
下面就直接粘贴进代码了
MStudent类
public class MStudent {
public String say() {
System.out.println("student:say");
return "student";
}
public void eat() {
System.out.println("student:eat");
}
}
主类APPS
public class APPS {
public static void main(String[] args) throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass mStudent=pool.get("com.telrob.sisit.MStudent");
//生成Anima接口
CtClass Anim=pool.makeInterface("com.tel.Anima");
Anim.addMethod(CtMethod.make("public String say();", Anim));
Anim.addMethod(CtMethod.make("public void eat();", Anim));
Anim.writeFile("D:/Project2/CGLIBS/target/classes");
//生成People类,继承MStudent类和Anima接口
CtClass People=pool.makeClass("com.tel.People");
People.setInterfaces(new CtClass[] {Anim});
People.setSuperclass(mStudent);
People.addMethod(CtMethod.make("public String say(){ return super.say(); }", People));
People.addMethod(CtMethod.make("public void eat(){ super.eat(); };", People));
CtConstructor ctConstructor = new CtConstructor(new CtClass[]{}, People);//无参数构造器
ctConstructor.setBody("{}");
People.writeFile("D:/Project2/CGLIBS/target/classes");
Class AnimC =Anim.toClass();
final Class PeopleC=People.toClass();
//调用Java 动态代理
Object anim=Proxy.newProxyInstance(APPS.class.getClassLoader(), new Class[] {AnimC}, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
method.invoke(PeopleC.newInstance(), args);
return null;
}
});
//调用say方法
Method says=AnimC.getMethod("say",null);
says.invoke(anim, null);
//调用eat方法
Method eat=AnimC.getMethod("eat", null);
eat.invoke(anim, null);
}
}
以上就是动态代理的全部代码,由于只是探讨整体的原理,所以就 没有对代码进行整理,忘大家见解。