java

位置:IT落伍者 >> java >> 浏览文章

JAVA 动态代理


发布日期:2023年08月02日
 
JAVA 动态代理

在目前的Java开发包中包含了对动态代理的支持但是其实现只支持对接口的的实现即只能对实现了接口的类进行动态代理对于没有实现任何借口的类不能进行动态代理其实现主要通过是javalangreflectProxy类和javalangreflectInvocationHandler接口

Proxy 类主要用来获取动态代理对象即动态代理类主要包括

Protected Proxy(InvocationHandler h)构造函数估计用于给内部的h赋值

Static Class getProxyClass (ClassLoader loader Class[] interfaces)获得一个代理类其中loader是类装载器interfaces是真实类所拥有的全部接口的数组

Static Object newProxyInstance(ClassLoader loader Class[] interfaces InvocationHandler h)返回代理类的一个实例返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)

InvocationHandler 接口用来约束调用者实现

该接口中仅定义了一个方法 Object: invoke(Object objMethod methodObject[] args)在实际使用时第一个参数obj一般指代理类method是被代理的方法args为该方法的参数数组这个抽象方法在代理类中动态实现

所谓Dynamic Proxy是这样一种class:它是在运行时生成的class在生成它时你必须提供一组interface给它然后该class就宣称它实现了这些interface你当然可以把该class的实例当作这些interface中的任何一个来用 当然啦这个Dynamic Proxy其实就是一个Proxy它不会替你作实质性的工作在生成它的实例时你必须提供一个handler由它接管实际的工作这两段摘自网络

我做了个小例子HelloWorld是业务接口HelloWorldImpl是业务接口的实现类HelloWorldHandler是动态代理类这个动态代理类与 HelloWorld 或者 HelloWorldImpl 或者 HelloKitty 没有任何直接的联系在调用这个代理类时传过来哪个业务接口的实现对象他就生成哪个对象的代理类

Java代码

package comwhyDynamicProxy;

/**

* 业务接口

* @author why

*

*/

public interface HelloWorld {

public void sayHello();

public String sayHelloWithReturnValue();

}

package comwhyDynamicProxy;

/**

* 业务接口

* @author why

*

*/

public interface HelloWorld {

public void sayHello();

public String sayHelloWithReturnValue();

}

Java代码

package comwhyDynamicProxy;

/**

* 业务接口实现类

* @author why

*

*/

public class HelloWorldImpl implements HelloWorld {

public void sayHello() {

Systemoutprintln(执行了 sayHello());

}

public String sayHelloWithReturnValue() {

String str = HelloWorld!;

Systemoutprintln(执行了 sayHelloWithReturnValue());

return str;

}

}

package comwhyDynamicProxy;

/**

* 业务接口实现类

* @author why

*

*/

public class HelloWorldImpl implements HelloWorld {

public void sayHello() {

Systemoutprintln(执行了 sayHello());

}

public String sayHelloWithReturnValue() {

String str = HelloWorld!;

Systemoutprintln(执行了 sayHelloWithReturnValue());

return str;

}

}

假如业务接口和实现类有很多我不能为每一个目标对象都设置一个代理于是写了一个对每一个目标对象都使用的代理类这个类的名字可能跟上面那两个家伙比较像但跟他们真的没有什么亲戚关系如果有一个类是 HelloKitty 的话来了也同样欢迎

Java代码

package comwhyDynamicProxy;

import javalangreflectInvocationHandler;

import javalangreflectMethod;

import javalangreflectProxy;

/**

* 动态代理类

* @author why

*

*/

public class HelloWorldHandler implements InvocationHandler {

//要代理的原始对象

private Object objOriginal;

/**

* 构造函数 (test 使用)

* @param obj 要代理的原始对象

*/

public HelloWorldHandler(Object obj) {

thisobjOriginal = obj ;

}

/**

* 无参数构造函数 (test 使用)

*

*/

public HelloWorldHandler() {

}

/**

* 返回此代理对象的实例 (test 使用)

* @param obj 要代理的原始对象

* @return

*/

public Object newProxy(Object obj) {

thisobjOriginal = obj ;

return ProxynewProxyInstance(objOriginalgetClass()getClassLoader() objOriginalgetClass()getInterfaces() this);

}

public Object invoke(Object proxy Method method Object[] args) throws Throwable {

Object result;

//方法调用之前

doBefore();

//调用原始对象的方法

result = methodinvoke(thisobjOriginal args);

//方法调用之后

doAfter();

return result;

}

private void doBefore() {

Systemoutprintln(before method invoke!);

}

private void doAfter() {

Systemoutprintln(after method invoke!);

}

}

package comwhyDynamicProxy;

import javalangreflectInvocationHandler;

import javalangreflectMethod;

import javalangreflectProxy;

/**

* 动态代理类

* @author why

*

*/

public class HelloWorldHandler implements InvocationHandler {

//要代理的原始对象

private Object objOriginal;

/**

* 构造函数 (test 使用)

* @param obj 要代理的原始对象

*/

public HelloWorldHandler(Object obj) {

thisobjOriginal = obj ;

}

/**

* 无参数构造函数 (test 使用)

*

*/

public HelloWorldHandler() {

}

/**

* 返回此代理对象的实例 (test 使用)

* @param obj 要代理的原始对象

* @return

*/

public Object newProxy(Object obj) {

thisobjOriginal = obj ;

return ProxynewProxyInstance(objOriginalgetClass()getClassLoader() objOriginalgetClass()getInterfaces() this);

}

public Object invoke(Object proxy Method method Object[] args) throws Throwable {

Object result;

//方法调用之前

doBefore();

//调用原始对象的方法

result = methodinvoke(thisobjOriginal args);

//方法调用之后

doAfter();

return result;

}

private void doBefore() {

Systemoutprintln(before method invoke!);

}

private void doAfter() {

Systemoutprintln(after method invoke!);

}

}

我写了两种获取动态代理对象实例的方法一种实在测试类中创建(test一种是通过代理类返回(test以下是测试代码

Java代码

package comwhyDynamicProxy;

import javalangreflectInvocationHandler;

import javalangreflectProxy;

public class Test {

/**

* JAVA 动态代理

* @param args

*/

public static void main(String[] args) {

/*

* test:在测试类中创建动态代理对象

*

* 首先获取一个业务接口的实现对象

* 获取一个InvocationHandler实现此处是HelloWorldHandler对象

* 创建动态代理对象

* 通过动态代理对象调用sayHello()和sayHelloWithReturnValue()方法此时会在原始对象HelloWorldImpl sayHello()和sayHelloWithReturnValue()方法前后输出两句字符串

*/

HelloWorld hw = new HelloWorldImpl();

InvocationHandler handler = new HelloWorldHandler(hw);

HelloWorld proxy = (HelloWorld) ProxynewProxyInstance(hwgetClass()getClassLoader()hwgetClass()getInterfaces()handler);

proxysayHello();

String str = proxysayHelloWithReturnValue();

Systemoutprintln(str = + str);

Systemoutprintln(\n\n);

/*

* test:从代理类中获取动态代理对象

*/

HelloWorldHandler handler = new HelloWorldHandler();

HelloWorld proxy = (HelloWorld)handlernewProxy(new HelloWorldImpl());

proxysayHello();

String str = proxysayHelloWithReturnValue();

Systemoutprintln(str = + str);

}

}

               

上一篇:利用 Java 存储过程简化数据库操作

下一篇:Java的垃圾回收之算法