静态、动态代理的若干问题
1、JDK动态代理实现步骤:
(1)第一步,实现InvocationHandler接口
Subject implements ISubject{
sayHello();
}
InvocationHandlerImpl implements InvocationHandler{
//委托类,就是被代理的那个类
ISubject subject
//构造函数,注入委托类t对象
InvocationHandlerImpl(ISubject subject){
this.subject = subject;
}
//这不是一条反射语句,只是被Proxy对象简单的调用
Object invoke(proxy,method,args){
//这里可以添加自定义方法,相当于切入面
//下面明显是一条反射语句
Object returnValue= method.invoke(this.subject,args);
//这里可以添加自定义方法
return returnValue;
}
}
(2)第二步,创建Proxy对象
//三个参数,类加载器,接口数组,InvocationHandler实例
//为什么是接口数组?因为存在Suject实现多个接口的情况,一个接口引用不可以调用另一个接口的方法,因为编译不通过
ISubject proxy = (ISubject)Proxy.newProxyInstance(loader,Isubject[],handler)
proxy.sayHello();
**总结:**可见JDK动态代理的代理业务代码全在Handler对象的invoke方法中,handler也持有委托类的对象,JDK使用的反射技术存在于invoke方法内和生成的proxy对象中。
问题1:JDK为什么只能代理实现了接口的类?
proxy对象是java.lang.reflect.Proxy的子类并实现了委托类的所有接口,即:
proxy extends Proxy implements ISubject
如果java可继承多个类的话,那么JDK就可以实现代理没有实现接口的类,代码是这样的(Subject没有接口):
proxy extends Proxy,Subject
又有个问题,proxy直接继承Subject不就可以了吗?
proxy extends Subject
其实我觉得这样也是可以的,只是子类代理了父类,我觉得JDK动态代理也是可以实现代理没有实现接口的类,可能是程序设计思想的缘故,里氏替换原则说子类尽量不要去重写父类的方法而应该 尽量去扩展父类。
问题2:动态代理和静态代理的区别
看过一些资料,动态代理和静态代理区别不清楚,各种解释啊,后来发现下面两种比较靠谱。
静态:由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。
动态:在程序运行时运用反射机制动态创建而成。
https://www.cnblogs.com/baizhanshi/p/6611164.html
https://www.jianshu.com/p/8176214e50e2
静态关键词:编译期,编译之后代理类的class字节码就生成了,编写一个普通代理类,主要有下面两种:
Proxy extends Subject{
Subject subject;
Proxy(ISubject subject){
this.subject = subject;
}
@Overrides
sayHello(){
this.subject.sayHello();
}
}
Proxy implements ISubject{
ISubject subject;
Proxy(ISubject subject){
this.subject = subject;
}
@Overrides
sayHello(){
this.subject.sayHello();
}
}
动态关键词:运行期,运行期才生成了代理类的class字节码。
同样一个好处也是不能忘记的,动态代理比静态代理好用的一个地方就是代理类不用去手动重写委托类的方法,静态代理的重写过程全部由代理类自动完成。
问题3:JDK和CGLIB动态代理的区别
1.JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。
2.JDK和Cglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。
3.JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法,Cglib执行效率更高。
https://www.cnblogs.com/monkey0307/p/8328821.html动态代理使我们免于去重写接口中的方法,而着重于去扩展相应的功能或是方法的增强,与静态代理相比简单了不少,减少了项目中的业务量
https://www.jianshu.com/p/07596979960d
别人写得好,这里就直接引用了。
上一篇: tomcat若干问题
下一篇: 电脑的威慑