Java动态代理,你不知道的都在这里。

先看再点赞,给自己一点思考的时间,如果对自己有帮助,微信搜索【程序职场】关注这个执着的职场程序员。
价值:Java技能,面试经验指导,简历优化,职场规划指导,技能提升方法,讲不完的职场故事,个人成长经验。

01

概念

动态代理是设计模式当中代理模式的一种。

主要用来做方法的增强,让你可以在不修改源码的情况下,增强一些方法,在方法执行前后做任何你想做的事情,因为在InvocationHandler的invoke方法中,你可以直接获取正在调用方法对应的Method对象,具体应用的话。
比如可以添加调用日志,做事务控制等。

随让上面说了很多的有点,但是也是存在不足的。

诚然,Proxy已经设计得非常优美,但是还是有一点点小小的遗憾之处,那就是它始终无法摆脱仅支持interface代理的桎梏,因为它的设计注定了这个遗憾。

回想一下那些动态生成的代理类的继承关系图,它们已经注定有一个共同的父类叫Proxy

Java的继承机制注定了这些动态代理类们无法实现对class的动态代理,原因是多继承在Java中本质上就行不通。

有很多条理由,人们可以否定对 class代理的必要性,但是同样有一些理由,相信支持class动态代理会更美好。

接口和类的划分,本就不是很明显,只是到了Java中才变得如此的细化。

如果只从方法的声明及是否被定义来考量,有一种两者的混合体,它的名字叫抽象类。实现对抽象类的动态代理,相信也有其内在的价值。此外,还有一些历史遗留的类,它们将因为没有实现任何接口而从此与动态代理永世无缘。

如此种种,不得不说是一个小小的遗憾。但是,不完美并不等于不伟大,伟大是一种本质,Java动态代理就是佐例。
 

Jdk动态代理之所以只能代理接口是因为代理类本身已经extends了Proxy,而java是不允许多重继承的,但是允许实现多个接口,因此才有这样的需要。


终于知道为什么说“Jdk动态代理局限于接口是因为Java只支持单继承”。

02

总结

1,JDK动态代理是基于接口的代理,其将代理接口中包括default方法在内的所有方法;
 

2,InvocationHandler是一个函数式接口(类似Runnable接口),其invoke方法指定方法的代理逻辑;
 

3,代理类的Method属性是接口中的方法对象,不是实现类的,注解加在接口方法上才能拿到;

03

使用步骤

1.通过实现InvocationHandler接口定义自己的InvocationHandler。

2.通过Proxy.getProxyClass0方法获得动态代理类。

3.通过反射机制获取动态代理类的构造方法,getConstructor(InvocationHandler.class)。

4.通过构造函数获得代理对象,并将第一步时自定义的InvocationHandler实例对象作为入参,newInstance(new Object[]{InvocationHandler})。

5.通过代理对象调用方法。
 

04

实战详解

1.定义需要被动态代理的接口

public interface Subject {
   
     void subjectRun(String param);}

2.被真正代理的类,用来处理实际业务

public class RealSubject implements Subject {
   
     public void subjectRun(String param) {
   
       System.out.println("代理对象的方法被执行了!"+param);  }}

3.定义代理类需实现InvocationHandler

public class ProxySubject implements InvocationHandler {
   
    //真正被代理的对象 private Object subject; //通过构造方法为代理对象赋值 public ProxySubject(Object subject){
   
     this.subject = subject; }/**     * @param proxy 动态生成的代理类     * @param method 被代理的类的方法     * @param args  调用被代理类的入参     * @return     * @throws Throwable     */@Overridepublic Object invoke(Object proxy, Method method, Object[] args)  throws Throwable {
   
     Object result = null;  System.out.println("目标对象方法执行之前对方法加强!");  method.invoke(subject,args);  //subject:被代理的对象 args:调用方法的入参  System.out.println("目标对象方法执行之前对方法加强!");  return result;}}

4.测试类

public class ProxyRun {
   
   public static void main(String[] args){
   
    //被真实代理的类,处理实际业务 Subject subject = new RealSubject(); //实现InvocationHandler的代理类 InvocationHandler h = new ProxySubject(subject); //动态生成代理类对象 Subject subjectProxy = (Subject)Proxy.newProxyInstance (h.getClass().getClassLoader(), subject.getClass().getInterfaces(),h); //调用动态生成代理类的方法 subjectProxy.subjectRun("execute"); }}

5.程序运行结果

目标对象方法执行之前对方法加强!代理对象的方法被执行了!execute目标对象方法执行之后对方法加强!

05

实战详解
最后给大家来一个代理模式结构图(来自网络)


我是【尔东双月】一枚执着的职场程序员,微信搜索【程序职场】关注我。别忘了三连啊,点赞、收藏、留言,随意给,我不挑。
知乎号: 程序职场
CSDN:程序职场
注:如果文章有任何问题,欢迎毫不留情地指正。

猜你喜欢

转载自blog.csdn.net/jianpengxuexikaifa/article/details/108431104