JAVA——动态代理(在别人的基础上稍作改动)

出处:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html

动态代理

概念

与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。

动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。

java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。

例子(用例子讲比较容易接受)

先给一个例子:

接口:BookFacade.java

委托类:BookFacadeImpl.java

代理类:BookFacadeProxy.java

主程序类:TestProxy.java 

本例的:

委托类实现接口BookFacade.java

代理类实现InvocationHandler 接口并等待接受委托类对象

主程序类:新建委托类对象,并传递给代理类,代理类返回代理类对象,实现动态代理。

具体代码如下:

BookFacade.java

package net.battier.dao;  
      
public interface BookFacade {  
    public void addBook();  
}  

BookFacadeImpl.java

package net.battier.dao.impl;  
  
import net.battier.dao.BookFacade;  
  
public class BookFacadeImpl implements BookFacade {  
    public void addBook() {  
        System.out.println("增加图书方法。。。");  
    }  
}  

BookFacadeProxy.java

package net.battier.proxy;  
  
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
import java.lang.reflect.Proxy;  
  
/** 
 * JDK动态代理代理类 
 *  
 * @author student 
 *  
 */  
public class BookFacadeProxy implements InvocationHandler {  
    private Object target;  
    /** 
     * 绑定委托对象并返回一个代理类 
     * @param target 
     * @return 
     */  
    public Object bind(Object target) {  
        this.target = target;  
        //取得代理对象  
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),  
                target.getClass().getInterfaces(), this);   //要绑定接口(这是一个缺陷,cglib弥补了这一缺陷)  
    }  
  
    @Override  
    /** 
     * 调用方法 
     */  
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        Object result=null;  
        System.out.println("事物开始");  
        //执行方法  
        result=method.invoke(target, args);  
        System.out.println("事物结束");  
        return result;  
    }  
  
}  

TestProxy.java

package net.battier.test;  
  
import net.battier.dao.BookFacade;  
import net.battier.dao.impl.BookFacadeImpl;  
import net.battier.proxy.BookFacadeProxy;  
  
public class TestProxy {  
  
    public static void main(String[] args) {  
        BookFacadeProxy proxy = new BookFacadeProxy();  
        BookFacade bookProxy = (BookFacade) proxy.bind(new BookFacadeImpl());  
        bookProxy.addBook();  
    }  
  
} 

JDK动态代理

JDK动态代理中包含一个类和一个接口:

InvocationHandler//接口:

public interface InvocationHandler { 
      public  Object  invoke( Object   proxy  ,Method   method  ,Object[]   args  )  throws Throwable; 
} 
/*
参数说明: 
Object proxy:指被代理的对象。 
Method method:要调用的方法 
Object[] args:方法调用时所需要的参数 
*/

Proxy类:

Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
/*
newProxyInstance(
ClassLoader loader,//类加载器 
 
Class<?>[] interfaces, //得到全部的接口 

InvocationHandler h   //得到InvocationHandler接口的子类实例

) 
*/

 Ps:类加载器 在Proxy类中的newProxyInstance()方法中需要一个ClassLoader类的实例,ClassLoader实际上对应的是类加载器,在Java中主要有一下三种类加载器; Booststrap ClassLoader:此加载器采用C++编写,一般开发中是看不到的; Extendsion ClassLoader:用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类; AppClassLoader:(默认)加载classpath指定的类,是最常使用的是一种加载器。 

接口的动态代理类的实例:(自己貌似有些混乱。。。)

/**** 方式一 ****/

//创建InvocationHandler对象
InvocationHandler handler = new MyInvocationHandler(...); 
//创建动态代理类
Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[] { Foo.class }); 
//创建动态代理类的实例
Foo foo = (Foo) proxyClass.getConstructor(new Class[] { InvocationHandler.class }).
newInstance(new Object[] { handler });   
/**** 方式二 ****/

//创建InvocationHandler对象
InvocationHandler handler = new MyInvocationHandler(...); 
//直接创建动态代理类的实例
Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class[] { Foo.class }, handler);  

自己的实例(虽并不规范,但是也有点特别的地方)

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
/**
 * 第二题:写一个ArrayList类的代理,实现和ArrayList中完全相同的功能.。
 * author:neo37927
 */
public class Test{
	public static void main(String[] args) throws Exception {
		//建立并传入ArrayList委托对象
		List realClass = new ArrayList();
		//接受代理类
		Object newList = newClass(realClass);
		//设定要调用的方法
		((List) newList).add("itheima");
		((List) newList).get(0);
		((List) newList).size();
		System.out.println(newList);
	}
	//动态代理,接受委托类(函数实现,本人以前是学C的,so...)
	public static   Object newClass(final Object realClass){
		//取得代理类对象,并返回
		return  Proxy.newProxyInstance(
					realClass.getClass().getClassLoader(),//第一个参数——加载类
					realClass.getClass().getInterfaces(),//第二个参数——取得接口
					new InvocationHandler() {//第三个参数——调用方法
						public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
							//执行方法
							Object result = method.invoke(realClass, args);
							return result;
						}
					}
				);
	}
}

网友龙四的代码

出处:http://bbs.csdn.net/topics/390301793?page=1

@ticmy

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
public class ListProxy {
	public static void main(String[] args) throws Exception {
		List<String> list = newList(String.class);
		list.add("abc");
		System.out.println(list);
	}
	
	
	@SuppressWarnings("unchecked")
	public static <T> List<T> newList(Class<T> elementType) {
		return (List<T>)Proxy.newProxyInstance(List.class.getClassLoader(), new Class[]{List.class}, new InvocationHandler() {
			private List<T> realList = new ArrayList<T>();
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				long start = System.nanoTime();
				Object ret = method.invoke(realList, args);
				long end = System.nanoTime();
				System.out.println("调用" + method.getName() + "耗时:" + (end - start) + "纳秒");
				return ret;
			}
		});
	}
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值