您的位置:首页 > 职场人生

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

2012-10-28 10:36 281 查看
----------- 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
中声明的
hashCode
equals

toString
方法的调用将按照与编码和指派接口方法调用相同的方式进行编码,并被指派到调用处理程序的
invoke
方法,也就是说InvocationHander实例覆盖hashCode ,equals和toString方法覆盖式有效的。这个目标类必须实现了接口的所有的方法,代理类就是很好的体现了面向接口编程。
----------- android培训java培训、java学习型技术博客、期待与您交流! ------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: