黑马程序员——java代理技术

  ------- android培训java培训、期待与您交流! ----------

1 基本概念理解

代理,这个名词在生活中很常见,如厂家生产的货品出售的时候会选择一些代理厂商帮助它出售自己的商品,这里厂商和代理都能完成出售商品这一共同目标,而且代理可以分布在各地,对厂商来讲有利于扩展销售群体,对买家来讲,方便自己的购物;在程序中的体现形式则是:为已经存在的多个具有相同接口的目标类的各个方法增加一些系统功能,如异常处理,日志,计算方法的运行时间,事务管理等。

示例如下:

class Sailing//该示例仅作为说明代理的概念和理解
{
Void sail()
  {
   System.out.println("卖出商品");
  }
}
//下面是代理类
class ProxySailing
{
Void sail()
  {

sailTime;//出售时间

       System.out.println("卖出商品");

  }
}

AOP,即面向切面的编程,系统中出现的交叉业务,如安全、事物、日志等,在编程的时候很多模块都会涉及到这些方面,但是将这些模块放到所有的实体对象中,又不合适,这时候我们就可以将这些功业务功能模块化。代理是实现AOP编程的核心和关键技术。

在代理方法中的如下四个位置加上系统功能代码:在调用目标方法之前;在调用目标方法之后;在调用目标方法前后;在处理目标方法异常的catch块中。

2 代理的使用

JVM可以在运行期间动态生成出类的字节码,这种动态生成的类被使用做代理类,即动态代理类  ,而且JVM生成的动态类只能作具有相同接口的目标类的代理(必须生成一个或多个接口。

表示动态代理的类,提供两个静态方法: 
a Class<?> getProxyClass(ClassLoader loader, Class<?>[] interface) 
用来产生代理类,参数要提供interface数组,它会生成这些interface的“虚拟实现”,用来表示真实的对象。 
b Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 
产生代理对象,多了InvocationHandler参数(只是InvocationHandler接口的实现类),它与代理对象关联,当请求分发到代理对象后,会自动执行h.invoke(...)方法,invoke方法就是来执行功能代码的地方。

使用 Java 动态代理的具体如下:
通过实现 InvocationHandler 接口创建自己的调用处理器;
通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

而在实际过程中由于Proxy 的静态方法 newProxyInstance 已经为我们封装了步骤 2 到步骤 4 的过程,因而使用过程更加简单。示例如下:

InvocationHandler handler = new InvocationHandlerImpl(..);   // InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发  
  // 通过 Proxy 直接创建动态代理类实例
Interface proxy = (Interface)Proxy.newProxyInstance( classLoader,   
     new Class[] { Interface.class },   
     handler );   

下面用一个完整的程序来具体说明代理的使用过程

package com.itheima;
//导入包
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;

class ProxyTest {

/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
//调用Proxy类的获取代理类方法,指定类加载器,多个接口,通常采用与接口相对应的类加载器,返回的是一个字节码的类
Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
System.out.println(clazzProxy1.getName());//打印代理类名

System.out.println("----------begin print constructors list----------");

Constructor[] constructors = clazzProxy1.getConstructors();//获取该对象的构造函数,返回一个集合
for(Constructor constructor : constructors){//使用高级for循环 获取构造函数的名称和变量类型信息
String name = constructor.getName();
StringBuilder sBuilder = new StringBuilder(name);
sBuilder.append('(');
Class[] clazzParams = constructor.getParameterTypes();//获取变量类型
for(Class clazzParam : clazzParams){
sBuilder.append(clazzParam.getName()).append(',');//变量输出时中间用,隔开
}
if(clazzParams!=null && clazzParams.length != 0)
sBuilder.deleteCharAt(sBuilder.length()-1);
sBuilder.append(')');
System.out.println(sBuilder.toString());//打印变量
}
System.out.println("----------begin print methods list----------");
Method[] methods = clazzProxy1.getMethods();//获取方法,返回一个Method类型的数组
for(Method method : methods){//使用高级for循环,打印方法信息
String name = method.getName();//获取方法名
StringBuilder sBuilder = new StringBuilder(name);
sBuilder.append('(');
Class[] clazzParams = method.getParameterTypes();//获取变量类型信息
for(Class clazzParam : clazzParams){
sBuilder.append(clazzParam.getName()).append(',');
}
if(clazzParams!=null && clazzParams.length != 0)//如果变量不为null并且长度不为0 ,去掉最后的一个","
sBuilder.deleteCharAt(sBuilder.length()-1);//显示的时候美观一些
sBuilder.append(')');
System.out.println(sBuilder.toString());
}

System.out.println("----------begin create instance object----------");
//Object obj = clazzProxy1.newInstance();
Constructor constructor = clazzProxy1.getConstructor(InvocationHandler.class);
class MyInvocationHander1 implements InvocationHandler{


public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
return null;//返回最简单的实现 ,返回值null
}
}
//获取collection类型的对象
Collection proxy1 = (Collection)constructor.newInstance(new MyInvocationHander1());

System.out.println(proxy1);
proxy1.clear();//清除集合
//传递匿名内部类形式的InvocationHandler对象作为参数
Collection proxy2 = (Collection)constructor.newInstance(new InvocationHandler(){


public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return null;
}
});

final ArrayList target = new ArrayList();//定义集合类型的目标对象
Collection proxy3 = (Collection)getProxy(target,new MyAdvice());
proxy3.add("zxx");//添加元素
proxy3.add("lhm");
proxy3.add("bxd")

System.out.println(proxy3.size());//获取长度

System.out.println(proxy3.getClass().getName());//获取代理类名
}
private static Object getProxy(final Object target,final Advice advice) {
Object proxy3 = Proxy.newProxyInstance(
target.getClass().getClassLoader(),//加载目标类的加载器
/*new Class[]{Collection.class},*/
target.getClass().getInterfaces(),//获取目标对象的所有接口
new InvocationHandler(){//采用匿名内部类方法得到Handler对象

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
advice.beforeMethod(method);
Object retVal = method.invoke(target, args);
advice.afterMethod(method);
return retVal;

}
}
);
return proxy3;//返回该代理
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值