您的位置:首页 > 编程语言 > Java开发

java动态代理(JDK和cglib)

2014-08-28 22:00 357 查看

java动态代理(JDK和cglib)

JAVA的动态代理
代理模式 :
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
按照代理的创建时期,代理类可以分为两种。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。

一、JDK动态代理:
直接使用JDK-API;
只能为实现了接口的类创建代理对象(通过接口形式创建对象)。
/**
* ①创建一个代理类JDKDynamicProxy实现InvocationHandler接口
* ②实现接口中的invoke方法
* ③在类中定义一个Object类型的属性,用来传递被代理对象
* ④提供一个带有Object类型的构造器
* ⑤创建一个方法getProxy返回一个对象,即为被代理对象的代理对象
*/

程序清单:
1.TestInterface接口
package com.softeem.dynamicproxy;

public interface TestInterface {
public void test01();
}
2.TestInterface实现接口
package com.softeem.dynamicproxy;

public class TestImplement implements TestInterface {
@Override
public void test01() {
System.out.println("这是JDK动态代理测试方法");
}
}
3.JDK动态代理
package com.softeem.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
* 直接使用JDK-API
* 只能为实现了接口的类创建代理对象(通过接口形式创建对象)
* ①创建一个代理类JDKDynamicProxy实现InvocationHandler接口
* ②实现接口中的invoke方法
* ③在类中定义一个Object类型的属性,用来传递被代理对象
* ④提供一个带有Object类型的构造器
* ⑤创建一个方法getProxy返回一个对象,即为被代理对象的代理对象
*/
public class JDKDynamicProxy implements InvocationHandler {

private Object obj;

public JDKDynamicProxy(Object obj) {
this.obj = obj;
}

//获取代理对象
public Object getProxy(){
Object proxyObj = null;
proxyObj = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
//要绑定接口(这是一个缺陷,cglib弥补了这一缺陷)
return proxyObj;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//tif.test01();第一个参数相当于tif,第二个参数相当于test01(),第三个参相当于参数

System.out.println("-------");

Object returnObj = method.invoke(obj, args);

System.out.println("<><><><>");
return returnObj;
}

}
4.Test测试类
package com.softeem.dynamicproxy;

public class Test {

public static void main(String[] args) {

TestImplement ti = new TestImplement();

//为ti对象创建代理对象
Object obj = new JDKDynamicProxy(ti).getProxy();//obj只存在于内存的对象

System.out.println(obj.getClass());

//因为jdk动态代理是通过接口创建的代理对象
TestInterface tif = (TestInterface) obj;
//TestInterface tif2 = new TestImplement();
//父类引用指向子类对象(多态),不能调用子类特有的方法,只能调用抽象方法中的类

//通过代理对象调用方法时,实际上是调用类代理类中的invoke方法
tif.test01();
}
}


二、cglib动态代理
使用到类第三方jar包:CGLib.jar不能为final类创建代理对象(通过子类创建代理对象)/**
* ①创建一个代理类CGLibDynamicProxy实现MethodInterceptor接口
* ②实现intercept方法
* ③在类中定义一个Object类型的属性,用来传递被代理对象
* ④提供一个带有Object类型的构造器
* ⑤创建一个方法getProxy返回一个对象,即为被代理对象的代理对象
*/
程序清单
1.cglib动态代理类CGLibDynamicProxy

package com.softeem.dynamicproxy;

import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
* 使用到类第三方jar包:CDLib.jar
* 不能为final类创建代理对象(通过子类创建代理对象)
* ①创建一个代理类CGLibDynamicProxy实现MethodInterceptor接口
* ②实现intercept方法
* ③在类中定义一个Object类型的属性,用来传递被代理对象
* ④提供一个带有Object类型的构造器
* ⑤创建一个方法getProxy返回一个对象,即为被代理对象的代理对象
*/
public class CGLibDynamicProxy implements MethodInterceptor {

private Object obj;

public CGLibDynamicProxy(Object obj) {
this.obj = obj;
}

public Object getProxy(){
//通过创建被代理对象的子类,来为其创建代理对象
Enhancer en = new Enhancer();
en.setSuperclass(obj.getClass());
en.setCallback(this);//回调

return en.create();
}

/**
* 在代理实例上处理方法调用并返回结果
*
* @param proxy
*            代理类
* @param method
*            被代理的方法
* @param params
*            该方法的参数数组
* @param methodProxy
* 			     代理的方法
*/
@Override
public Object intercept(Object arg0, Method method, Object[] arg2,
MethodProxy arg3) throws Throwable {
System.out.println("-------");
Object returnObj = method.invoke(obj, arg2);
System.out.println("<<><><><><>>");
return returnObj;
}
}
2.CGLibTest测试类
package com.softeem.dynamicproxy;

public class CGLibTest {

public static void main(String[] args) {

TestImplement ti = new TestImplement();

CGLibDynamicProxy cgdp = new CGLibDynamicProxy(ti);
//创建ti的代理对象obj
Object obj = cgdp.getProxy();

//通过创建被代理对象类的子类来创建的代理对象
//所以可以讲代理对象直接强转成被代理对象的类型
TestImplement t = (TestImplement) obj;

t.test01();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 动态代理