黑马程序员技术交流社区
标题:
代理
[打印本页]
作者:
eycrckag
时间:
2013-6-6 14:20
标题:
代理
什么是JAVA代理机制,什么是JAVA动态代理机制.
作者:
librazeng
时间:
2013-6-6 14:42
你这头像真恶心,不是为了积分,真不想回答。
代理机制:代理模式是一种常见的设计模式,代理就是控制对目标类(委托类)的访问,代理类和目标类实现了相同的接口,代理是为了给目标对象提供额外的功能或处理,比如异常处理、运行时间、事务管理等等。代理对象并不提供真正的服务,而是调用目标对象的方法提供服务。
动态代理:就是在程序运行时,用反射机制动感创建出来的代理类。对于没有实现接口的类,可以用其子类实现代理。
贴个实现代码:
public class ProxyTest{
/**1.创建一个实现了Collection接口的动态代理类
* 2.列出动态类的所有构造方法和参数签名
* 3.列出动态类的所有方法和参数签名
* 4.创建动态类的实例对象:用反射获得构造函数
* 1)编写一个InvocationHandle类
* 2)调用构造方法传入InvocationHandle实例对象创建动态类实例
* 3)用匿名内部类的形式创建动态类对象的代理
* @param args
* @throws IllegalAccessException
* @throws InstantiationException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalArgumentException
*/
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
//1.创建一个实现了Collection接口的动态代理类
System.out.println("----------get a proxy with collection----------");
//获取代理类Proxy的字节码文件对象,传入classloader、接口类的字节码文件
Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
//System.out.println(ProxyTest.class.getClassLoader());//AppClassLoader
System.out.println(clazzProxy1.getName());//动态类名:$Proxy0
//2.列出动态类的所有构造方法和参数签名
System.out.println("----------proxy constructors list----------");
Constructor[] constructors=clazzProxy1.getConstructors();
StringBuilder sb=null;
for(Constructor constructor:constructors){
String name=constructor.getName();//$Proxy0
sb=new StringBuilder(name);
sb.append('(');
//遍历构造函数的参数,添加进字符串缓冲区中
Class[] clazzParas=constructor.getParameterTypes();
for(Class clazzPara:clazzParas){
// sb.append(clazzPara.getName()+",");
sb.append(clazzPara.getName()).append(",");
}
if(clazzParas!=null&&clazzParas.length!=0)
sb.deleteCharAt(sb.length()-1);
sb.append(')');
//输出每个构造方法名称和参数列表
System.out.println(sb);//$Proxy0(java.lang.reflect.InvocationHandler)
}
//3.列出动态类的所有方法和参数签名
System.out.println("----------proxy methods list----------");
Method[] methods=clazzProxy1.getMethods();
StringBuilder sb2=null;
for(Method method:methods){
String name=method.getName();//$Proxy0
sb2=new StringBuilder(name);
sb2.append('(');
//遍历方法的参数,添加进字符串缓冲区中
Class[] clazzParas=method.getParameterTypes();
for(Class clazzPara:clazzParas){
sb2.append(clazzPara.getName()).append(",");
}
if(clazzParas!=null&&clazzParas.length!=0)
sb2.deleteCharAt(sb2.length()-1);
sb2.append(')');
//将每个方法名和参数列表打印出来
System.out.println(sb2);
}
//4.创建动态类的实例对象
System.out.println("---------creat object of proxy--------");
//创建方法一:获取代理类的有参构造器new对象
//Object obj=clazzProxy1.newInstance();不能直接用Class创建对象,因为没有无参构造器
//创建参数类型实例,传入类的有参构造
Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class);
class myInvocationHandler1 implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return null;
}
}
Collection proxy1=(Collection)constructor.newInstance(new myInvocationHandler1());
System.out.println(proxy1);//null
/*代理类从Object类继承的方法中,只有hashcode equalse toString3个方法委托给
InvocationHandler,即会调用目标对象*/
proxy1.clear();
//proxy1.size();
//创建方法二:直接在代理类的有参构造器中传入参数对象
Collection proxy2=(Collection)constructor.newInstance(new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
return null;
}
});
//创建方法三:通过代理类Proxy的newProxyInstance方法直接创建对象
//newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)
final ArrayList target = new ArrayList();//被代理的对象,实现了Collection的集合
//传入目标对象、系统功能代码,调用getProxy,生成动态代理对象
Collection proxy3 =(Collection)getProxy(target,new Advicer());
//测试,用动态代理类调用目标对象方法
proxy3.add("xiaotao");
proxy3.add("panhong");
proxy3.add("liaojun");
/*动态代理类内部方法
$Proxy0{
InvocationHandler handler;
public $Proxy0(InvocationHandler handler){
this.handler=handler;
}
add(Object obj){
return handler.invoke(this, this.getClass().
getMethod("add",Object.class),obj)
}
}
*/
System.out.println(proxy3.size());
//clazzProxy1.newInstance();
}
//将目标和系统功能代码抽出封装成一个getProxy方法
private static Object getProxy(final Object target,final Advice advice) {
Object proxy3=(Object)Proxy.newProxyInstance(
//定义代理类的类加载器
//调用newProxyInstance方法时必须与目标类的类加载器和接口一致
//类A调用了类B,那么B的类加载器就要用A的
target.getClass().getClassLoader(),
//代理类要实现的接口列表
//new Class[]{Collection.class},
target.getClass().getInterfaces(),
//传入构造函数调用的InvocationHandle类对象
new InvocationHandler(){
/* InvocationHandler代理实例的调用处理程序 实现的接口,
* 通过实现该接口定义横切逻辑,并反射调用目标类的代码,
* 动态将横切逻辑和业务逻辑编织在一 起
*/
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
/*proxy是代理实例,一般不会用到;
*method是代理实例上的方法,反射调用目标类;
*args是通过代理类传入 的方法参数,在反射调用时使用
*/
/*
//系统功能:测试程序运行时间
long startTime=System.currentTimeMillis();
//调用目标方法,将其从return抽出来,加入代理所需的代码
Object retVal=method.invoke(target, args);
//系统功能:测试程序运行时间
long endTime=System.currentTimeMillis();
//打印测试
System.out.println(method.getName() +
" run time of " + (endTime - startTime));
return retVal;
*/
//系统功能:测试程序运行时间
advice.beforeMethod(method);
//调用目标方法,将其从return抽出来,加入代理所需的代码
Object retVal=method.invoke(target, args);
//系统功能:测试程序运行时间
//打印测试
advice.afterMethod(method);
return retVal;
}
});
return proxy3;
}
}
//Advice接口
package cn.reflect.demo;
import java.lang.reflect.Method;
public interface Advice {
/**
* 执行的系统功能接口
* @param args
*/
abstract void beforeMethod(Method method);
abstract void afterMethod(Method method);
}
//实现Advice接口的Advicer
package cn.reflect.demo;
import java.lang.reflect.Method;
/**
* @param args
*/
public class Advicer implements Advice {
long startTime;
@Override
public void beforeMethod(Method method) {
System.out.print("我们恋爱了!");
startTime=System.currentTimeMillis();
}
@Override
public void afterMethod(Method method) {
System.out.print("我们又恋爱了!");
long endTime=System.currentTimeMillis();
System.out.println(method.getName() +" run time of " +
(endTime - startTime));
}
public static void main(String[] args) {
}
}
复制代码
作者:
李阳阳
时间:
2013-6-9 13:51
这是我自己总结的不过不太全面,希望对你有帮助、
动态代理总结.zip
(6.13 KB, 下载次数: 50)
2013-6-9 13:50 上传
点击文件名下载附件
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2