黑马程序员__Java中的代理类
来源:互联网 发布:java mq消息队列 编辑:程序博客网 时间:2024/06/06 04:38
----------------------android培训、java培训、期待与您交流! ----------------------
代理类Proxy
代理类的作用:客户端调用的目标类,需要添加一些功能(如日志、异常运行时间等),但是不能修改目标类代码,这种情况用代理类来实现。
即,用一类实现目标类中的所以方法。在方法内调用目标类中对应的方法,并在调用前或后添加上功能代码。让客户端调用代理类。
这里,目标类必须实现了某些接口。而代理类必须实现目标类已实现的接口。
交叉业务: 系统中存在交叉业务,一个交叉业务就是要切入到系统中的一个方面。就是,多个不同类中的不同方法,都实现了一些相同的功能,如安全、日志、事务等,
这些功能代码也就是交叉代码,就像个切面切入到这些方法中。若每个类中都写相同的功能代码很麻烦,那么就使交叉业务模块化,只写一份代码。
AOP:面向方面的编程 Aspect oriented program,AOP的目标就是要使交叉业务模块化。
可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的
使用代理技术正好可以解决这种问题,代理是实现AOP功能的核心和关键技术。
动态代理类:
引入:要为系统中的各种接口的类增加代理功能,那将需要太多的代理类,全部采用静态代理方式,将是一件非常麻烦的事情!
概念:JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
特点:
1.JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。
如果要为一个没有实现接口的类生成动态代理类,怎么办?---->那么可以使用CGLIB库。
CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,
代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码:
1.在调用目标方法之前
2.在调用目标方法之后
3.在调用目标方法前后
4.在处理目标方法异常的catch块中
2.代理对象调用方法时,会委托给InvocationHandler,InvocationHandler中的invoke方法返回的值Object,就是代理对象调用方法后的结果。
但是,并不是所有的方法都会进行委托。代理类从Object类继承的方法中,只有3个方法 hashCode、equals、toString会进行委托,其他都不。
动态代理类应用:可 生成代理和插入通告的通用方法中,将目标类对象target和新业务对象advice作为参数传入。在InvocationHandler的invoke方法中,advice调用方法来添加新业务。
Proxy中的方法:
构造方法:只有一个 protected Proxy(InvocationHandler h);
InvocationHandler是个接口,其中只有一个方法:
Object invoke(Object proxy, Method method, Object[] args) 在代理实例上处理方法调用并返回结果。
其中,proxy是代理类的实例,method是代理对象调用的方法,args是方法传入的参数。
static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) 返回代理类的字节码文件,并向其提供类加载器和接口数组。
loader:累加器,interfaces:目标类实现了的接口。通常累加器会定义为接口的累加器。
例如:获取Collection的代理类字节码--->Proxy.getProxyClass(Collection.class.getLoader(),Collection.class);
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler) 直接获取代理类的实例
其中,loader是目标类的加载器,interfaces是目标类实现的所有接口,handler是创建代理对象时传入的参数。
获取代理类对象的三种方法:以获取Collection的代理类为例
Class clazzProxy=Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
1.先获取动态代理类,然后创建对象。
Constructor constructor=clazzProxy.getConstructor(InvocationHandler.class);
class MyInvocationHandler implements InvocationHandler
{
public Object invoke(Object proxy,Method method,Object[] args)throws Throwable
{
return null;
}
}
Collection proxy1=constructor.newInstance(new MyInvocationHandler());
2.Collection proxy2=constructor.newInstance(new InvocationHandler(){
public Object invoke(Object proxy,Method method,Object[] args)throws Throwable
{
return null;
}
});
3.直接创建动态代理类对象。
Collection proxy3=Proxy.newProxyInstance(
Collection.class.getClassLoader(),
new Object[]{Collection.class},
new InvocationHandler(){
ArrayList target=new ArrayList();//不能放入invoke方法中。这样的话,代理类每次调用方法都会创建目标类对象target。
public Object invoke(Object proxy,Method method,Object[] args)throws Throwable
{
long beginTime=System.getCurrentTimeMillise();
Object retValue=method.invoke(target,args);
long endTime=System.getCurrentTimeMillise();
System.out.println(method.getName()+"...run time of..."+(endTime-beginTime));
return retValue;
}
});
proxy3.add("adsg");
proxy3.size();
可 生成代理和插入通告的通用方法
ArrayList target=new ArrayList();
Advice advice = new MyAdvice();
//代理类对象只能转换成接口
Collection proxyArr=(Collection)getProxy(target,advice);
proxyArr.size();
private static Object getProxy(final Object target,final Advice advice) {
Object proxy=Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler(){
@Override
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 proxy;
}
public class MyAdvice implements Advice {
private long beginTime;
public void beforeMethod(Method method) {
beginTime=System.currentTimeMillis();
}
public void afterMethod(Method method) {
long endTime=System.currentTimeMillis();
System.out.println(method.getName()+" running time of "+(endTime-beginTime));
}
}
----------------------详细请查看:http://edu.csdn.net/heima---------------------------------------
- 黑马程序员__Java中的代理类
- 黑马程序员__Java中的注解
- 黑马程序员__Java中的泛型
- 黑马程序员__JAVA基础加强--类加载器和代理总结
- 黑马程序员__JAVA基础__String类
- 黑马程序员__Java概述
- 黑马程序员__Java高新技术一
- 黑马程序员__Java高新技术二
- 黑马程序员__Java 集合学习
- 黑马程序员__java 数组学习
- 黑马程序员__java GUI学习
- 黑马程序员__Java基础语法
- 黑马程序员__java基础__GUI
- 黑马程序员__Java接口定义
- 黑马程序员__Java异常处理
- 黑马程序员__Java输入输出流
- 黑马程序员__Java多线程Thread
- 黑马程序员__java之反射
- J2EE之DAO设计模式简介与实例
- ACM模板
- 【Log4j】如何让自己的java web工程使用log4j?
- 拓展欧几里德算法
- VC6窗体dll,带热键,自身卸载(源码及教程)
- 黑马程序员__Java中的代理类
- usaco Betsy's Tour
- 关于利用myeclipse开发基于xfire的webservice
- 关于this和super关键字的一点整理
- ubuntu下使用Xdebug
- 蛋疼的NDK r7的NUL文件名bug
- 黑马程序员__Java中的泛型
- 从一道面试题解析static的作用
- 黑马程序员__Java中的注解