A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© eycrckag 中级黑马   /  2013-6-6 14:20  /  1094 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

什么是JAVA代理机制,什么是JAVA动态代理机制.

评分

参与人数 1技术分 +1 收起 理由
刘胜寒 + 1

查看全部评分

2 个回复

倒序浏览
你这头像真恶心,不是为了积分,真不想回答。
代理机制:代理模式是一种常见的设计模式,代理就是控制对目标类(委托类)的访问,代理类和目标类实现了相同的接口,代理是为了给目标对象提供额外的功能或处理,比如异常处理、运行时间、事务管理等等。代理对象并不提供真正的服务,而是调用目标对象的方法提供服务。

动态代理:就是在程序运行时,用反射机制动感创建出来的代理类。对于没有实现接口的类,可以用其子类实现代理。
贴个实现代码:
  1. public class ProxyTest{

  2.         /**1.创建一个实现了Collection接口的动态代理类
  3.          * 2.列出动态类的所有构造方法和参数签名
  4.          * 3.列出动态类的所有方法和参数签名
  5.          * 4.创建动态类的实例对象:用反射获得构造函数
  6.          * 1)编写一个InvocationHandle类
  7.          * 2)调用构造方法传入InvocationHandle实例对象创建动态类实例
  8.          * 3)用匿名内部类的形式创建动态类对象的代理
  9.          * @param args
  10.          * @throws IllegalAccessException
  11.          * @throws InstantiationException
  12.          * @throws SecurityException
  13.          * @throws NoSuchMethodException
  14.          * @throws InvocationTargetException
  15.          * @throws IllegalArgumentException
  16.          */
  17.         public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
  18.                 //1.创建一个实现了Collection接口的动态代理类
  19.                 System.out.println("----------get a proxy with collection----------");
  20.                 //获取代理类Proxy的字节码文件对象,传入classloader、接口类的字节码文件
  21.                 Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
  22.                 //System.out.println(ProxyTest.class.getClassLoader());//AppClassLoader
  23.                 System.out.println(clazzProxy1.getName());//动态类名:$Proxy0
  24.                 //2.列出动态类的所有构造方法和参数签名
  25.                 System.out.println("----------proxy constructors list----------");
  26.                 Constructor[] constructors=clazzProxy1.getConstructors();
  27.                 StringBuilder sb=null;
  28.                 for(Constructor constructor:constructors){
  29.                         String name=constructor.getName();//$Proxy0
  30.                         sb=new StringBuilder(name);
  31.                         sb.append('(');
  32.                         //遍历构造函数的参数,添加进字符串缓冲区中
  33.                         Class[] clazzParas=constructor.getParameterTypes();
  34.                         for(Class clazzPara:clazzParas){
  35.                                 //        sb.append(clazzPara.getName()+",");
  36.                                         sb.append(clazzPara.getName()).append(",");
  37.                         }
  38.                         if(clazzParas!=null&&clazzParas.length!=0)
  39.                                         sb.deleteCharAt(sb.length()-1);
  40.                         sb.append(')');
  41.                         //输出每个构造方法名称和参数列表
  42.                         System.out.println(sb);//$Proxy0(java.lang.reflect.InvocationHandler)
  43.                 }
  44.                 //3.列出动态类的所有方法和参数签名
  45.                 System.out.println("----------proxy methods list----------");
  46.                 Method[] methods=clazzProxy1.getMethods();
  47.                 StringBuilder sb2=null;
  48.                 for(Method method:methods){
  49.                         String name=method.getName();//$Proxy0
  50.                         sb2=new StringBuilder(name);
  51.                         sb2.append('(');
  52.                         //遍历方法的参数,添加进字符串缓冲区中
  53.                         Class[] clazzParas=method.getParameterTypes();
  54.                         for(Class clazzPara:clazzParas){
  55.                                         sb2.append(clazzPara.getName()).append(",");
  56.                                 }
  57.                         if(clazzParas!=null&&clazzParas.length!=0)
  58.                                 sb2.deleteCharAt(sb2.length()-1);
  59.                                 sb2.append(')');
  60.                                 //将每个方法名和参数列表打印出来
  61.                                 System.out.println(sb2);
  62.                 }
  63.                 //4.创建动态类的实例对象
  64.                 System.out.println("---------creat object of proxy--------");
  65.                 //创建方法一:获取代理类的有参构造器new对象
  66.                 //Object obj=clazzProxy1.newInstance();不能直接用Class创建对象,因为没有无参构造器
  67.                 //创建参数类型实例,传入类的有参构造
  68.                 Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class);
  69.                 class myInvocationHandler1 implements InvocationHandler{
  70.                         @Override
  71.                         public Object invoke(Object proxy, Method method, Object[] args)
  72.                                         throws Throwable {
  73.                                 return null;
  74.                         }
  75.                 }
  76.                 Collection proxy1=(Collection)constructor.newInstance(new myInvocationHandler1());
  77.                 System.out.println(proxy1);//null
  78.                 /*代理类从Object类继承的方法中,只有hashcode  equalse toString3个方法委托给

  79.                 InvocationHandler,即会调用目标对象*/

  80.                 proxy1.clear();
  81.                 //proxy1.size();
  82.                 //创建方法二:直接在代理类的有参构造器中传入参数对象
  83.                 Collection proxy2=(Collection)constructor.newInstance(new InvocationHandler(){
  84.                 @Override
  85.                 public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
  86.                         return null;
  87.                         }
  88.                 });
  89.                        
  90.                 //创建方法三:通过代理类Proxy的newProxyInstance方法直接创建对象
  91.                 //newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)
  92.                 final ArrayList target = new ArrayList();//被代理的对象,实现了Collection的集合
  93.                 //传入目标对象、系统功能代码,调用getProxy,生成动态代理对象
  94.                 Collection proxy3 =(Collection)getProxy(target,new Advicer());
  95.                 //测试,用动态代理类调用目标对象方法
  96.                 proxy3.add("xiaotao");
  97.                 proxy3.add("panhong");
  98.                 proxy3.add("liaojun");
  99.                 /*动态代理类内部方法
  100.                  $Proxy0{
  101.                         InvocationHandler handler;
  102.                         public $Proxy0(InvocationHandler handler){
  103.                                 this.handler=handler;
  104.                         }
  105.                         add(Object obj){
  106.                                 return handler.invoke(this, this.getClass().
  107.                                                         getMethod("add",Object.class),obj)
  108.                                 }
  109.                         }
  110.                         */
  111.                         System.out.println(proxy3.size());  
  112.                                         //clazzProxy1.newInstance();
  113.         }
  114.         //将目标和系统功能代码抽出封装成一个getProxy方法
  115.         private static Object getProxy(final Object target,final Advice advice) {
  116.                 Object proxy3=(Object)Proxy.newProxyInstance(
  117.                                 //定义代理类的类加载器
  118.                                 //调用newProxyInstance方法时必须与目标类的类加载器和接口一致

  119.                                 //类A调用了类B,那么B的类加载器就要用A的
  120.                                 target.getClass().getClassLoader(),
  121.                                 //代理类要实现的接口列表  
  122.                                 //new Class[]{Collection.class},
  123.                                 target.getClass().getInterfaces(),
  124.                                 //传入构造函数调用的InvocationHandle类对象
  125.                                 new InvocationHandler(){
  126.                                         /* InvocationHandler代理实例的调用处理程序 实现的接口,
  127.                                          * 通过实现该接口定义横切逻辑,并反射调用目标类的代码,
  128.                                          * 动态将横切逻辑和业务逻辑编织在一 起
  129.                                          */
  130.                                        
  131.                                         @Override
  132.                                         public Object invoke(Object proxy, Method method,
  133.                                                         Object[] args) throws Throwable {
  134.                                                 /*proxy是代理实例,一般不会用到;
  135.                                                 *method是代理实例上的方法,反射调用目标类;
  136.                                                 *args是通过代理类传入 的方法参数,在反射调用时使用
  137.                                                 */
  138.                                                 /*
  139.                                                 //系统功能:测试程序运行时间
  140.                                                 long startTime=System.currentTimeMillis();
  141.                                                 //调用目标方法,将其从return抽出来,加入代理所需的代码
  142.                                                 Object retVal=method.invoke(target, args);
  143.                                                 //系统功能:测试程序运行时间
  144.                                                 long endTime=System.currentTimeMillis();
  145.                                                 //打印测试
  146.                                                  System.out.println(method.getName() +
  147.                                                         " run time of " + (endTime - startTime));
  148.                                                 return retVal;
  149.                                                 */
  150.                                                 //系统功能:测试程序运行时间
  151.                                                 advice.beforeMethod(method);
  152.                                                 //调用目标方法,将其从return抽出来,加入代理所需的代码
  153.                                                 Object retVal=method.invoke(target, args);
  154.                                                 //系统功能:测试程序运行时间
  155.                                                 //打印测试
  156.                                                 advice.afterMethod(method);
  157.                                                 return retVal;
  158.                                         }
  159.                                 });
  160.                 return proxy3;
  161.         }
  162. }

  163. //Advice接口
  164. package cn.reflect.demo;

  165. import java.lang.reflect.Method;

  166. public interface Advice {
  167.                 /**
  168.                  * 执行的系统功能接口
  169.                  * @param args
  170.                  */
  171.                 abstract  void beforeMethod(Method method);
  172.                 abstract void afterMethod(Method method);
  173. }
  174. //实现Advice接口的Advicer
  175. package cn.reflect.demo;

  176. import java.lang.reflect.Method;
  177. /**
  178. * @param args
  179. */
  180. public class Advicer implements Advice {
  181.          long startTime;
  182.         @Override
  183.         public void beforeMethod(Method method) {
  184.                 System.out.print("我们恋爱了!");
  185.                 startTime=System.currentTimeMillis();
  186.         }
  187.         @Override
  188.         public void afterMethod(Method method) {
  189.                 System.out.print("我们又恋爱了!");
  190.                 long endTime=System.currentTimeMillis();
  191.                 System.out.println(method.getName() +" run time of " +
  192.                  (endTime - startTime));
  193.         }
  194.         public static void main(String[] args) {

  195.         }
  196. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
Sword + 1

查看全部评分

回复 使用道具 举报
这是我自己总结的不过不太全面,希望对你有帮助、
动态代理总结.zip (6.13 KB, 下载次数: 50)



评分

参与人数 1技术分 +1 收起 理由
Sword + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马