静态代理,动态代理是什么? JDK动态代理,cglib动态代理。
目录
什么是代理模式?
角色:一个接口(一类业务
public interface Rent {
public void rent();
public void add();
public void delete();
}
接口的实现类(具体的实现方法
public class Host implements Rent{
@Override
public void rent() {
System.out.println("租房子了");
}
public void add(){
System.out.println("增加");
}
public void delete(){
System.out.println("删除");
}
}
用户想要使用这个具体的方法 就需要调用 具体的实现类 impl
但是又不想直接访问 就用另外一个代理类来代替他 做一个封装
静态代理
生成一个 HostP 对象,这个对象内部可以实现原先 host 的所有功能,并且可以扩展一些功能,但实际上里面的功能还是由 host 提供的。
public class HostP implements Rent{
private Host host;
public void setHost(Host host) {
this.host = host;
}
@Override
public void rent() {
host.rent();
}
@Override
public void add() {
host.add();
}
public void delete(){
System.out.println("delete 租户");
}
}
代理模式的优缺点
使用代理模式具有以下几个优点:
1、代理模式能将代理对象与真实被调用的目标对象分离。
2、一定程度上降低了系统的耦合度,扩展性好。
3、可以起到保护目标对象的作用。
4、可以对目标对象的功能增强。
当然,代理模式也是有缺点的:
1、代理模式会造成系统设计中类的数量增加。
2、在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。
3、增加了系统的复杂度。
————————————————
版权声明:本文为CSDN博主「Leon_Jinhai_Sun」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Leon_Jinhai_Sun/article/details/109553543
动态代理
JDK动态代理实现
技术:java反射
前提:代理的类实现了接口。
通过newProxyInstance()函数获得proxy对象,这个对象就代理了实现了这个接口所有的类,然后使用这个代理对象即可。 代理对象会自动调用相应的方法。比如
-
IRpcHelloService RpcHello = RpcProxy.create(IRpcHelloService.class);
-
System.out.println(RpcHello.hello("Tom老师"));
RpcHello
是 IRpcHelloService.class这个接口的代理类,IRpcHelloServiceImpl实现了这个接口,那么RpcHello.hello("Tom老师")就相当于调用了IRpcHelloServiceImpl中的hello方法。
newProxyInstance,方法有三个参数:
loader: 用哪个类加载器去加载代理对象
interfaces:动态代理类需要实现的接口
h:动态代理方法在执行时,会调用h里面的invoke方法去执行
public class ProxyHost implements InvocationHandler {
private Object target;
// 注入一个实现类
public void setTarget(Object target) {
this.target = target;
}
// 根据实现类 拿到其实现的方法
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(),this);
}
// 在使用时直接调用方法即可
// 调用时就会通过 invoke来实现
@Override
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable {
System.out.println("调用方法前的日志");// 在调用原对象的方法时 可以增强
Object result = method.invoke(target,args);
System.out.println("调用方法后的日志");
return result;
}
}
cglib动态代理
静态代理 动态代理比较
Cglib和jdk动态代理的区别?
Cglib和jdk动态代理的区别及运行性能比较 – 沐春风-燕南飞 – 博客园
经测试,jdk创建对象的速度远大于cglib,这是由于cglib创建对象时需要操作字节码。
cglib执行速度略大于jdk,所以比较适合单例模式。
1、Jdk动态代理:利用拦截器(必须实现InvocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理
2、 Cglib动态代理:利用ASM框架,对代理对象类生成的class文件加载进来,通过修改其字节码生成子类来处理
什么时候用cglib什么时候用jdk动态代理?
1、目标对象生成了接口 默认用JDK动态代理
2、如果目标对象使用了接口,可以强制使用cglib
3、如果目标对象没有实现接口,必须采用cglib库,Spring会自动在JDK动态代理和cglib之间转换
JDK动态代理和cglib字节码生成的区别?
1、JDK动态代理只能对实现了接口的类生成代理,而不能针对类
2、Cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,并覆盖其中方法的增强,但是因为采用的是继承,所以该类或方法最好不要生成final,对于final类或方法,是无法继承的
Cglib比JDK快?
1、cglib底层是ASM字节码生成框架,但是字节码技术生成代理类,在JDL1.6之前比使用java反射的效率要高
2、在jdk6之后逐步对JDK动态代理进行了优化,在调用次数比较少时效率高于cglib代理效率
3、只有在大量调用的时候cglib的效率高,但是在1.8的时候JDK的效率已高于cglib
4、Cglib不能对声明final的方法进行代理,因为cglib是动态生成代理对象,final关键字修饰的类不可变只能被引用不能被修改
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/92849.html