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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 王_强 中级黑马   /  2013-3-22 10:25  /  1996 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

  • 在这里生成与代理类相关联的InvocationHandler对象 :
  • 这句话是什么意思?
  • public class LogHandler implements InvocationHandler {  
  •       
  •     private Object dele;  
  •       
  •     public LogHandler(Object obj) {  
  •         this.dele = obj;  
  •     }  
  •       
  •     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  •         doBefore();  
  •         //在这里完全可以把下面这句注释掉,而做一些其它的事情  
  •        Object result = method.invoke(dele, args);
  •        //这句话又是什么意思,是利用了反射吗?
  •         after();  
  •         return result;  
  •     }  
  •       
  •     private void doBefore() {  
  •         System.out.println("before....");  
  •     }  
  •       
  •     private void after() {  
  •         System.out.println("after....");  
  •     }  
  • }
  • 这几天在看动态代理,感觉挺难的,总是把握不住总体脉络!
  • 求高手详细指点下,谢谢!



点评

如果问题未解决,请继续追问回复者,如果问题已经解决,请将分类改为“已解决”,谢谢  发表于 2013-3-22 12:32

评分

参与人数 1技术分 +1 收起 理由
洪建超 + 1

查看全部评分

7 个回复

倒序浏览
代理类我觉得记住来两点吧:第一个是目标类,第二个是功能类
面向AOP的编程,代理是为原来的类(目标)增加新的功能。
Object result = method.invoke(dele, args);这句话是反射,而其中的dele就是目标类,上下两句话(doBefore();和 after(); )就是新增加的功能
目标类和新功能组合出类的新类就是代理类即Proxy.newProxyInstance返回的对象

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
我试图在比较难的代码加上注释
public class LogHandler implements InvocationHandler {//  继承InvocationHandler,重写invoke方法
      
    private Object dele;  
      
    public LogHandler(Object obj) {  
        this.dele = obj;  //传来你要代理的类
    }  
      
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
        doBefore();  
        Object result = method.invoke(dele, args);//反射实现dele方法
        after();  
        return result;  //前后增加方法后返回代理类
    }  
      
    private void doBefore() {  
        System.out.println("before....");  
    }  
      
    private void after() {  
        System.out.println("after....");  
    }  
}

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
qintoko 发表于 2013-3-22 10:51
我试图在比较难的代码加上注释
public class LogHandler implements InvocationHandler {//  继承Invocati ...


Object result = method.invoke(dele, args);//反射实现dele方法
这句话,其实我发现这样写也可以

method.invoke(dele, args);

返回值时:
return null;

也可以正确执行!
为什么很多的程序要那么写呢?不懂?
回复 使用道具 举报
王_强 发表于 2013-3-22 11:33
Object result = method.invoke(dele, args);//反射实现dele方法
这句话,其实我发现这样写也可以

你是要增加after和before的方法才使用代理的,什么都不返回,何必代理呢?直接用原来的类不就行了
回复 使用道具 举报
王_强 发表于 2013-3-22 11:33
Object result = method.invoke(dele, args);//反射实现dele方法
这句话,其实我发现这样写也可以

忘了说谢谢,你的回复,我基本懂了,希望能回复我之前最后一个问题。
回复 使用道具 举报
谢洋 高级黑马 2013-3-22 11:59:16
7#
下面是个人笔记,希望对你有帮助
/*static Object newProxyInstance(ClassLoader loader, Class<?>[] *interfaces, InvocationHandler h)  
     *正在执行的add()方法:原形
     * add(args){
     * public Object invoke(Object proxy,Method method,Object[] args){
     *         //调用target  的add方法 的代码method.invoke()
     *     }
     * }
     */

生成代理的原理分析:
1、  通过目标实例,得到加载目标实例的类加载器,及目标类的实现的所有接口;
2、  通过InvocationHandler接口产生个子类对象:调用处理器;
3、  并把上面所得到的东西作为参数传给Poxy的静态方法newProxyInstance()
4、  该方法并执行Class cl = getProxyClass(loader, interfaces),得到代理类的字节码
5、  得到代理类指定参数所构造:Constructor cons = cl.getConstructor(constructorParams);
6、  有了构造就可以建立代理实例了:return (Object) cons.newInstance(new Object[] { h });
7、  源代码:上面分析跟源代码差不多吧
private final static Class[] constructorParams =
    { InvocationHandler.class };
public static Object newProxyInstance(ClassLoader loader,
                    Class<?>[] interfaces,
                    InvocationHandler h)
    throws IllegalArgumentException
    {
        if (h == null) {
        throw new NullPointerException();
    }
    /*
     * Look up or generate the designated proxy class.
     */
    Class cl = getProxyClass(loader, interfaces);
    /*
* Invoke its constructor with the designated invocation handler.
     */
    try {
        Constructor cons = cl.getConstructor(constructorParams);
        return (Object) cons.newInstance(new Object[] { h });
    } catch (NoSuchMethodException e) { }
从上面分析及上面源代码可以知道:代理实例只能实现接口的方法,并不是实现了目标类的所有方法。

点评

很好,不错!  发表于 2013-3-22 14:53

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
王_强 发表于 2013-3-22 11:36
忘了说谢谢,你的回复,我基本懂了,希望能回复我之前最后一个问题。

为什么很多的程序要那么写呢?不懂?
//是这个问题吗?

这就要牵扯到代理出现的历史渊源,早期版本是没有代理的,如果增加方法有如下途径:
1,修改原始类
2,添加抽象类来继承

但是这两种方式的弊端
1,会造成父类和子类的大量修改 -->出现BUG的不可预计性将会大大增加
2,会造成子类的继承途径发生巨大修改(因为一个子类只能继承一个父类)

在这种情况下,JAVA才出现了代理,目的是方便程序员。

不知道是不是您想要的答案
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马