黑马程序员--Java高新技术代理类

----------- android培训java培训、java学习型技术博客、期待与您交流! -----

代理类的概念和作用。

生活中的代理,济南人想买海尔的电脑,可以从济南海尔代理商那里购买,也可以直接跑到青岛来买海尔的电脑。主体的业务目标是一样的,就是买了一台电脑,从代理处购买既可以省时也省力,虽然有一些代理费,但是比自己跑到青岛买还是会便宜一些。

应用程序中的代理。编写一个和目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法是加上系统功能代码。如果采用工厂模式和配置文件的方式进行管理,在配置文件中使用目标类,还是代理类,这样很容易切换。譬如,想要日志功能是就配置代理类,否则配置目标类,这样增加系统功能很容易。张老师在这里体现了面向对象的一个很重要的思想,即面向接口的编程

交叉业务编程问题即为面向方面编程(Aspect oriented Program  AOP),AOP的目标就是要使用交叉业务模块化。可以采用将切面代码移到原始方法周围,这与直接在方法中编写切面代码的效果一样。例如学生服务,课程服务,教室服务到都用到了,安全,事务,日志的功能,这些安全、事务、日志就是交叉业务。

动态代理技术。JVM可以再运行期动态生成类的字节码,这种动态生成的类,往往被用作代理类。JVM生成的动态类必须实现一个或多个接口,所以java生成的动态类只能用作具有相同接口的目标的目标类的代理。

CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类动态生成代理类,那么可以使用CGLIB库。系统功能添加代码的位置:调用目标方法之前,调用目标方法之后,调用目标方法前后,处理目标方法异常模块catch中。

创建动态类及其查看方法列表信息代码如下:

//获取代理类
  Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
  System.out.println(clazzProxy1.getName());
  //创建缓冲区
  StringBuilder sb = new StringBuilder();
  //取得构造方法集合,并遍历该集合
  Constructor[] constructors =clazzProxy1.getConstructors();
  for (Constructor construtor : constructors) {
   //System.out.println(constructor.getName());
    //sb=new StringBuilder();
   sb.append(construtor.getName());
   sb.append('(');
   Class[] clazzParams=construtor.getParameterTypes();
   for (Class clazzParam : clazzParams) {
    sb.append(clazzParam.getName()).append(',');
   }
   if(clazzParams.length!=0&&clazzParams!=null){
    sb.deleteCharAt(sb.length()-1);
   }
  
   sb.append(')'); 
   //System.out.println(sb.toString());
   sb.append("\r\n");
  }
  //取得代理类的方法集合,并遍历
  Method[] methods =clazzProxy1.getMethods();
  for (Method method : methods) {
   //System.out.println(constructor.getName());
    //sb=new StringBuilder();
   sb.append(method.getName());
   sb.append('(');
   Class[] clazzParams=method.getParameterTypes();
   for (Class clazzParam : clazzParams) {
    sb.append(clazzParam.getName()).append(',');
   }
   if(clazzParams.length!=0&&clazzParams!=null){
    sb.deleteCharAt(sb.length()-1);
   }
  
   sb.append(')'); 
   //System.out.println(sb.toString());
   sb.append("\r\n");
  }
  System.out.println(sb.toString());

对于方法的遍历,因为代理类要有一个接口类,所以所以方法含有接口中的所有的方法。

创建动态类的实例及其调用方法

Collection foo3 = (Collection) Proxy.newProxyInstance(Collection.class
    .getClassLoader(), new Class[] { Collection.class },
    new InvocationHandler() {
     ArrayList target = new ArrayList();

     @Override
     public Object invoke(Object proxy, Method method,
       Object[] args) throws Throwable {
     long startTime=System.currentTimeMillis();
      Object retValue = method.invoke(target, args);
      long endTime=System.currentTimeMillis();
      System.out.println("Runtime:"+(endTime-startTime));      return retValue;
     }
    });

  foo3.add("zhangsan");
  System.out.println(foo3.toString());
  System.out.println(foo3.size());

动态生成类每次操作都会调用invocationHandler实现类的invoke方法,他会把自己的操作方法和参数传给InvocationHandler方法,真正的操作在InvocationHandler中实现,所以将target作为成员变量。 在代理实例上的java.lang.Object 中声明的hashCodeequalstoString 方法的调用将按照与编码和指派接口方法调用相同的方式进行编码,并被指派到调用处理程序的invoke 方法,也就是说InvocationHander实例覆盖hashCode ,equals和toString方法覆盖式有效的。这个目标类必须实现了接口的所有的方法,代理类就是很好的体现了面向接口编程。

 ----------- android培训java培训、java学习型技术博客、期待与您交流! ------------

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值