java动态代理一(java自带动态代理)

来源:互联网 发布:学校网络舆情自查报告 编辑:程序博客网 时间:2024/06/06 07:28


1.什么是动态代理?

答:动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实。代理一般会实现它所表示的实际对象的接口。代理可以访问实际对象,但是延迟实现实际对象的部分功能,实际对象实现系统的实际功能,代理对象对客户隐藏了实际对象。客户不知道它是与代理打交道还是与实际对象打交道。

2.按照代理的创建时期,代理类可以分为两种。 
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。 
动态代理:在程序运行时,运用反射机制动态创建而成。 

第一种情况:假如我去租房,没有经过中介,直接找到了房屋的主人。这里抽象一下就是我直接访问了真实对象(房屋的主人),然后我把房屋给租了。

第二种情况:假如我去租房,需要经过中介,找到一家租房的中介公司,然后把房屋租了。这里抽象一下就是我访问了真实对象的代理对象(中介),这里的代理对象(中介)需要持有真实对象(房屋主人)才能把房屋租给我(因为中介手里没有房子,他肯定要有房屋真实主人的房子才行)。结构图如下:


大家一定要明白的是,代理对象(中介)一定要持有真实对象(房屋主人)才行。


3.静态代理的实现

/**  * 定义一个账户接口  *   * @author Administrator  *   */  public interface Count {      // 查看账户方法      public void queryCount();        // 修改账户方法      public void updateCount();    }  </span>

import net.battier.dao.Count;    /**  * 委托类(包含业务逻辑)  *   * @author Administrator  *   */  public class CountImpl implements Count {        @Override      public void queryCount() {          System.out.println("查看账户方法...");        }        @Override      public void updateCount() {          System.out.println("修改账户方法...");        }    }    CountProxy.java  package net.battier.dao.impl;    import net.battier.dao.Count;    /**  * 这是一个代理类(增强CountImpl实现类)  *   * @author Administrator  *   */  public class CountProxy implements Count {      private CountImpl countImpl;        /**      * 覆盖默认构造器      *       * @param countImpl      */      public CountProxy(CountImpl countImpl) {          this.countImpl = countImpl;      }        @Override      public void queryCount() {          System.out.println("事务处理之前");          // 调用委托类的方法;          countImpl.queryCount();          System.out.println("事务处理之后");      }        @Override      public void updateCount() {          System.out.println("事务处理之前");          // 调用委托类的方法;          countImpl.updateCount();          System.out.println("事务处理之后");        }    }  


package net.battier.test;    import net.battier.dao.impl.CountImpl;  import net.battier.dao.impl.CountProxy;    /**  *测试Count类  *   * @author Administrator  *   */  public class TestCount {      public static void main(String[] args) {          CountImpl countImpl = new CountImpl();          CountProxy countProxy = new CountProxy(countImpl);          countProxy.updateCount();          countProxy.queryCount();        }  }  

4.动态代理例子

目前Java开发包中包含了对动态代理的支持,但是其实现只支持对接口的的实现。 其实现主要通过java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。 

Proxy类主要用来获取动态代理对象,InvocationHandler接口用来约束调用者实现

以下为模拟案例,通过动态代理实现在方法调用前后向控制台输出两句字符串


定义一个HelloWorld接口

package com.ljq.test; /** * 定义一个HelloWorld接口 *  * */ public interface HelloWorld {    public void sayHelloWorld();}


类HelloWorldImpl是HelloWorld接口的实现

package com.ljq.test; /** * 类HelloWorldImpl是HelloWorld接口的实现 * */ public class HelloWorldImpl implements HelloWorld{    public void sayHelloWorld() {        System.out.println("HelloWorld!");    }}


HelloWorldHandler是 InvocationHandler接口实现

package com.ljq.test; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * 实现在方法调用前后向控制台输出两句字符串 *  * @author jiqinlin * */ public class HelloWorldHandler implements InvocationHandler{    //要代理的原始对象     private Object obj;        public HelloWorldHandler(Object obj) {        super();        this.obj = obj;    }    /**     * 在代理实例上处理方法调用并返回结果     *      * @param proxy 代理类     * @param method 被代理的方法     * @param args 该方法的参数数组     */    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        Object result = null;        //调用之前         doBefore();        //调用原始对象的方法        result=method.invoke(obj, args);        //调用之后        doAfter();        return result;    }        private void doBefore(){        System.out.println("before method invoke");    }        private void doAfter(){        System.out.println("after method invoke");    }    }




测试类

package com.ljq.test;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class HelloWorldTest {    public static void main(String[] args) {        HelloWorld helloWorld=new HelloWorldImpl();        InvocationHandler handler=new HelloWorldHandler(helloWorld);                //创建动态代理对象        HelloWorld proxy=(HelloWorld)Proxy.newProxyInstance(                helloWorld.getClass().getClassLoader(),                 helloWorld.getClass().getInterfaces(),                 handler);        proxy.sayHelloWorld();    }}


参数说明: 
Object proxy:指被代理的对象。 
Method method:要调用的方法 
Object[] args:方法调用时所需要的参数 

可以将InvocationHandler接口的子类想象成一个代理的最终操作类,替换掉ProxySubject。 

Proxy类: 
Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法: 
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, 
InvocationHandler h) 
                               throws IllegalArgumentException 
参数说明: 
ClassLoader loader:类加载器 
Class<?>[] interfaces:得到全部的接口 
InvocationHandler h:得到InvocationHandler接口的子类实例 



0 0
原创粉丝点击