黑马程序员技术交流社区

标题: 代理的一点疑惑 [打印本页]

作者: 彭润生    时间: 2012-9-16 10:34
标题: 代理的一点疑惑
本帖最后由 彭润生 于 2012-9-19 10:39 编辑

  Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);  
  Constructor cr = clazz.getConstructor(InvocationHandler.class);
final ArrayList src = new ArrayList();
  class MyInvocationHandler implements InvocationHandler{
   @Override
   public Object invoke(Object proxy, Method method, Object[] args)
     throws Throwable {
      return method.invoke(src, args);
   }
  }
System.out.println(cr.newInstance(new MyInvocationHandler()).getClass());//这个返回的是class $Proxy0这个类
  System.out.println(((Collection)cr.newInstance(new MyInvocationHandler())).getClass());//那么为什么可以用Collection强转,还有强转后为什么打印的还是$Proxy0这个类呢?   
  //求解释
  
作者: 张 涛    时间: 2012-9-16 11:12
3.((Collection)cr.newInstance(new MyInvocationHandler())).getClass()//最后collection的代理getclass,当然得到proxy了。
2.(Collection)cr.newInstance(new MyInvocationHandler())//Arrylist是collection的子类,当然可以得到Collection的代理类
1.cr.newInstance(new MyInvocationHandler());这是通过构造方法new一个实例,返回值是ArrayList的代理。这个可以用“.class”试试,打印出也是proxy。
作者: 彭润生    时间: 2012-9-16 12:15
张 涛 发表于 2012-9-16 11:12
3.((Collection)cr.newInstance(new MyInvocationHandler())).getClass()//最后collection的代理getclass, ...

那么加这个强转就是申明是这个类的代理吗?
作者: 佟亚鹏    时间: 2012-9-16 12:17
你的 Proxy.getProxyClass传进去的被代理接口是Collection,你用的生成接口的api,不太方便,直接用,Proxy.newInstance,它接受三个参数,第一个参数为被代理对象的类加载器,第二个参数为需要代理的接口,这些接口的所有方法都会被代理,第三个参数为建立的InvocationHandler的实例,现在就举个例子说明吧

由于Jdk提供的代理只能代理接口,所以首先我们先建议一个被代理的接口还有他的实现,就用项目中的dao层演示

现在有个用户访问数据库的Userdao,里面有个保存用户的方法,接受一个名字

  1. public interface UserDao {
  2. void save(String username);
  3. }
  4. UserDao的实现类UserDaoImpl
  5. public class UserDaoImpl implements UserDao {
  6. @Override
  7. public void save(String username) {
  8.   System.out.println(username + "存进了数据库");  
  9. }
  10. }
  11. 现在想对UserDaoImpl记录日志,写一个处理类LogHandler实现InvocationHandler接口
  12. public class LogHandler implements InvocationHandler {
  13. //被代理的对象
  14. private Object target;
  15. @Override
  16. public Object invoke(Object proxy, Method method, Object[] args)
  17.    throws Throwable {
  18.   //对被代理对象target的对应方法进行调用,把代理类接受的参数传递进去
  19.   Object result = method.invoke(target, args);
  20.   System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "用户" + args[0] + "保存进数据库");
  21.   return result;
  22. }

  23. //接收被代理的对象
  24. public LogHandler(Object target) {
  25.   super();
  26.   this.target = target;
  27. }
  28. }
  29. 用于测试的有main的类  ProxyTest
  30. public class ProxyTest {
  31. public static void main(String[] args) {
  32.   //被代理的UserDaoImpl对象
  33.   UserDao ud = new UserDaoImpl();
  34.   //生成代理对象,转成UserDao引用使用,注意这里不能转为UserDaoImpl的引用,只能使用对应接口,
  35.   //这是由于接口可以规范方法
  36.   UserDao proxy = (UserDao)Proxy.newProxyInstance(
  37.        ud.getClass().getClassLoader()//加载生成代理类的加载器
  38.        , ud.getClass().getInterfaces()//需要代理的接口,这里为UserDao
  39.        , new LogHandler(ud));//日志处理类
  40.   //对代理对象调用save方法
  41.   proxy.save("黑马程序员");
  42. }
  43. }
复制代码

控制台打印:

黑马程序员存进了数据库
2012-09-06 14:12:23用户黑马程序员保存进数据库

怎么样,这样就为UserDaoImpl动态的增加了功能,呵呵,动态代理不好理解,多看几遍张老师的java高新技术视频吧,每次看都会有新的收获,楼主,加油。。。。



作者: 彭润生    时间: 2012-9-16 14:16
佟亚鹏 发表于 2012-9-16 12:17
你的 Proxy.getProxyClass传进去的被代理接口是Collection,你用的生成接口的api,不太方便,直接用,Proxy. ...

呵呵,还没有学到你的这个程度,呵呵。一起加油




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2