JDK的动态(静态)代理机制(转载并整理修改)

动态代理代码如下:

package proxy.myproxy.dynamicProxy;

public interface UserDao {
    void save();
}

package proxy.myproxy.dynamicProxy;

public class UserDaoImpl implements UserDao {

    public void save() {
        System.out.println("UserDao save()");
    }

}

package proxy.myproxy.dynamicProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class InvocationHandlerImpl implements InvocationHandler {
    
    
    //表明被代理对象
    private Object target;
    
    public InvocationHandlerImpl(Object target){
        this.target = target;
    }
    
    public Object invoke(Object proxy, Method method, Object[] args)//args是那个你执行的那个方法的参数
            throws Throwable {
       System.out.println(proxy.getClass());//这里输出:class $Proxy0,可以看出proxy是什么
        System.out.println(target.getClass());//这里输出:class proxy.myproxy.dynamicProxy.UserDaoImpl,可以看出target是什么
        System.out.println("开始记录日志");       
        //调用被代理对象的对应方法
        Object obj = method.invoke(target, args);//obj是方法执行完之后的返回值
        System.out.println("结束记录日志");
        return obj;
    }
}

package proxy.myproxy.dynamicProxy;

import java.lang.reflect.Proxy;

public class Test {
    public static void main(String[] args) {
        UserDao userDao = new UserDaoImpl();
        //产生代理对象,采用组合方式,因此代理对象与被代理对象须实现相同接口
        UserDao userDaoProxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), new InvocationHandlerImpl(userDao));
       //方法调用时都会将自身传递给InvocationHandler,顺带将代理对象与参数一并传过来,
       //使用invoke(Object proxy, Method method, Object[] args)方法
        userDaoProxy.save();
        
    }
}

解释:

1.     Proxy即动态代理类;

2.     Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用;

它有三个参数:

ClassLoader loader    ----指定被代理对象的类加载器,我们产生的代理对象中实际上包含了被代理对象

Class[] Interfaces    ----指定被代理对象所以事项的接口

InvocationHandler h  ----指定需要调用的InvocationHandler对象

3.     实现InVocationHandler接口的InvocationHandlerImpl对象

这个对象的invoke()方法就是Proxy这个动态代理类所代理的接口类的抽象方法的真实实现;

它有三个参数:

Object proxy          -----代理类对象

Method method         -----被代理对象的方法(这里不是接口的抽象方法了,是具体的实现类中的方法)

Object[] args         -----该方法的参数数组


userDaoProxy.save();的实现可以这样理解:

/*class $Proxy0 
 * {
 *   //上边的方法写是无参的,这个是有参
 *   save(User u){
 *   Method m = UserDAO.getclass.getmethod 
 *   li.invoke(this,m,u);
 *   }
 * }
 */

JDK中具体的动态代理类是怎么产生的呢?

1.产生代理类$Proxy0类

执行了Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

将产生$Proxy0类,它继承Proxy对象,并根据第二个参数,实现了被代理类的所有接口,自然就可以生成接口要实现的所有方法了(这时候会重写hashcode,toString和equals三个方法),但是还没有具体的实现体;

2.    将代理类$Proxy0类加载到JVM中

这时候是根据Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)它的第一个参数----就是被代理类的类加载器,把当前的代理类加载到JVM中

3.    创建代理类$Proxy0类的对象

调用的$Proxy0类的$Proxy0(InvocationHandler)构造函数,生成$Proxy0类的对象

参数就是Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)它的第三个参数

这个参数就是我们自己实现的InvocationHandler对象,我们知道InvocationHandler对象中组合加入了代理类代理的接口类的实现类;所以,$Proxy0对象调用所有要实现的接口的方法,都会调用InvocationHandler对象的invoke()方法实现;

4.    生成代理类的class byte

动态代理生成的都是二进制class字节码





静态代理代码如下:

package proxy.myproxy.staticProxy;
public interface UserDao {
    void save();
}

package proxy.myproxy.staticProxy;
public class UserDaoImpl implements UserDao {

    public void save() {
        System.out.println("UserDao save()");
    }

}


package proxy.myproxy.staticProxy;

public class UserDaoImplProxy implements UserDao {
    
    private UserDao userDao = new UserDaoImpl();//合成   也可以传个引用过来
    
    
    
    public void save() {
        
        System.out.println("开始记录日志。。。");
        
        userDao.save();
        
        System.out.println("结束记录日志。。。。");
        
    }
}


package proxy.myproxy.staticProxy;
public class Test {
    public static void main(String[] args) {
        UserDao userDao =  new UserDaoImplProxy();
        System.out.println("test123");
        userDao.save();
     
    }
}

参考:http://www.cnblogs.com/fuckqq/archive/2012/10/04/jdk_proxy.html

&&  http://hi.baidu.com/wolf55/item/7f39971451f9ed4ee75e068f

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值