关于java 动态代理详细讲解

来源:互联网 发布:怎么卖域名 编辑:程序博客网 时间:2024/05/29 14:10

        近来比较闲,又看来下java代理的api 感觉之前对他的理解不是很深  现在又重新看了一遍 记录下自己的感受吧!

   那么我们认识下 什么是代理呢? 小弟语文学的不好 ,就用如下代码来说吧! 

      我们模仿 登录 注册 业务案列 来讲解   

/*** 定义登录接口**/interface login{  boolean login(String username,String password);  boolean creadUser(String username,String password);}/*** 实现登录接口**/class loginImpl implements login {@Overridepublic boolean login(String username, String password) {System.out.println("出来核心登录逻辑"+ "帐号是 : "+username +"     密码是:    "+ password);return true;}@Overridepublic boolean creadUser(String username, String password) {System.out.println("我只是注册 不需要家其他业务处理" +"    注册的帐号:  "+username +" 注册时的密码   :   "+password);return true;}}            /** *  *  登录成功也需要添加业务逻辑   * @author jade * */class Pox extends loginImpl{@Overridepublic boolean login(String username, String password) {        System.out.println("登录前业务添加逻辑 pox 1 静态代理");      boolean is=  super.login(username, password);        System.out.println("登录后业务添加逻辑 pox 1 静态代理");return is;}} /**  ----------------------------- 讲解代理 开始  end        ***/

  如上 Pox 的存在原因是因为需求的变动,又不想去改动原来的业务 所以他就出现了!  Pox 就是传说中的代理  

上面代理的缺点显易见 - 一个代理只能为一个接口服务  为了解决这个问题  java 就出来了动态代理  

那就何为动态代理 ? 说白了就是 一个接口《java.lang.reflect.invocationHandler》 一个类《java.lang.reflect 类 Proxy》  如何不是和了解的 话几分钟看下api  好那我们把上面的静态代理修改成jdk 动态代理




class Pox2 implements InvocationHandler{private Pox p;Pox2(){};               Pox2(Object o){this.p=o;}////Object getPox(Object o){////this.p = o;  //        //取得代理对象  //        return Proxy.newProxyInstance(o.getClass().getClassLoader(),  //        o.getClass().getInterfaces(), this);            //  得到代理对象有很多方式 可以参阅 api  我这里写了两种一个是通过构造函数得到 一个是通过调用getPox :查了网上论坛大部分用//的是getPox  ////}@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {   Object r=null;     //    如下演示 业务处理   if(method.getName().equals("login")){   System.out.println("登录前业务添加逻辑 pox 2 动态代理");   r= method.invoke(p, args);  System.out.println("登录后业务添加逻辑 pox 2 动态代理");      }else{   r= method.invoke(p, args);      }return r;}}



 如上就实现了 jdk 动态的代理拉 简单吧   来个测试类吧

public class StadyPox {public static void main(String[] args) {   InvocationHandler proxy2 = new Pox2(new loginImpl());                   login login3=(login) Proxy.newProxyInstance(loginImpl.class.getClassLoader(),loginImpl.class.getInterfaces() , proxy2); login3.login("c", "d"); login3.creadUser("e", "f");
</pre><pre name="code" class="java">//----------------------  如上是通过构造函数 实现的 如下是直接通过getPox()得到
<pre name="code" class="java" style="color: rgb(146, 147, 175); font-size: 11px;">//   login login2 = (login) proxy2.getPox(new loginImpl());  //   login2.login("a", "b"); 
 //                <span style="font-family: Times;">login2</span><span style="font-family: Times;">.creadUser("e", "f");</span>
}}

 关于动态代理的讲解就到这里了  看下

Proxy.newProxyInstance(loginImpl.class.getClassLoader(),loginImpl.class.getInterfaces() , proxy2) 你看到了什么呢? loginImpl.class.getInterfaces() ?? 这个的意思就是 他必须有实现接口 那就是jdk 动态代理 必须要有接口 才能使用 

那如果在没有接口的情况下 那我们如何实现动态代理 ??  cglib  代理

      cglib 代理 其原理是 继承实现类 在继承的原则下面覆盖父类方法体  也就是  final 类不能代理 因为 他不能被继承

再次模拟 登录业务 讲解 cglib   

class loginImpl2 {public boolean login(String username, String password) {System.out.println("出来核心登录逻辑"+ "帐号是 : "+username +"     密码是:    "+ password);return true;}public boolean creadUser(String username, String password) {System.out.println("我只是注册 不需要家其他业务处理" +"    注册的帐号:  "+username +" 注册时的密码   :   "+password);return true;}}

由上面代码可以看出 , 没有实现接口  。如下写cglib 代理类  写法方式和jdk 代理类似


class cglib  implements MethodInterceptor{ private Object pox;           public Object getPox(Object o) {          pox = o;          Enhancer enhancer = new Enhancer();          enhancer.setSuperclass(this.pox.getClass());          // 回调方法          enhancer.setCallback(this);          // 创建代理对象          return enhancer.create();      }        @Override      // 回调方法      public Object intercept(Object obj, Method method, Object[] args,              MethodProxy proxy) throws Throwable {          System.out.println("事物开始");          proxy.invokeSuper(obj, args);          System.out.println("事物结束");                        return null;          }    }
以上就是cglib动态代理      来个测试下吧!
class TestCglib {public static void main(String[] args) {loginImpl2 login4 = new loginImpl2();cglib cglibProxy = new cglib();loginImpl2 hw = (loginImpl2) cglibProxy.getInstance(login4);System.out.println(hw.getClass().getSuperclass());System.out.println("ssksksk      " + login4.getClass().getSuperclass());hw.login("aa", "bb");}}


得出的结果:

class jada.java.lang.reflect.loginImpl2

ssksksk      class java.lang.Object

事物开始

出来核心登录逻辑帐号是 : aa     密码是:    bb

事物结束



class jada.java.lang.reflect.loginImpl2   有此可以得出  --他说继承了 loginImpl2    

开始出来个疑问 直接打印代理类

System.out.println(hw)  结果是null  并且它执行了一次 <span style="color: rgb(146, 147, 175);font-size:18px;"></span><pre name="code" class="java"> public Object intercept(Object obj, Method method, Object[] args,              MethodProxy proxy) throws Throwable        



同样的方式 我打印了 jdk动态实现的

public class StadyPox {public static void main(String[] args) {loginImpl a = new loginImpl();InvocationHandler proxy2 = new Pox2(a);login login3 = (login) Proxy.newProxyInstance(loginImpl.class.getClassLoader(),loginImpl.class.getInterfaces(), proxy2);System.out.println(a);System.out.println(login3);login3.login("c", "d");// login login2 = (login) new Pox2().bingTage(new loginImpl());// login2.login("a", "b");}}
 出来的结果是:

jada.java.lang.reflect.loginImpl@2e8f4fb3

jada.java.lang.reflect.loginImpl@2e8f4fb3

登录前业务添加逻辑 pox 2 动态代理

出来核心登录逻辑帐号是 : c     密码是:    d

登录后业务添加逻辑 pox 2 动态代理











      

0 0
原创粉丝点击