概述:
java提供的动态代理技术允许开发者在运行期间创建接口的代理实例,这个动态代理必须的基于接口才能使用,主要设计到java.lang.reflect包下的两个类:Proxy和InvocationHandler,其中InvocationHandler是个接口,可以通过实现该接口定义横切逻辑,并通过反射机制调用目标代码,动态将横切逻辑和业务逻辑编织在一起。JDK的动态代理技术在Spring框架中也有使用。
下面是JDK动态代理的一个实例,涉及到一个接口,接口的实现类,一个InvocationHandler接口的实现类,以及一个测试类:
IStudentService接口:
package cn.qing.java.reflect;
public interface IStudentService {
public String findStudent(String stuName);
public int findStudentNum();
}
StudentServiceImpl接口实现类:
package cn.qing.java.reflect;
public class StudentServiceImpl implements IStudentService {
public String findStudent(String stuName) {
System.out.println("findStudent method....");
return "name:\t"+stuName;
}
public int findStudentNum() {
System.out.println("findStudentNum method ...");
return 20;
}
}
MyInvocationHandler类:
package cn.qing.java.reflect;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target)
{
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("befor execute method:"+method.getName());
System.out.println("可以在这里添加一些前置操作....");
//通过反射技术调用具体的方法
Object obj = method.invoke(target, args);
System.out.println("after execute method:"+method.getName());
System.out.println("可以在这里添加一些后置操作....");
return obj;
}
}
测试类TestProxy:
package cn.qing.java.reflect;
import java.lang.reflect.Proxy;
public class TestProxy {
/**
* @param args
*/
public static void main(String[] args) {
TestProxy tp = new TestProxy();
IStudentService ss = tp.getIStudentServiceInstance();
ss.findStudent("xiaoming");
System.out.println("*****************************");
ss.findStudentNum();
}
/**
* 通过JDK动态代理返回IStudentService代理对象
* @return
*/
public IStudentService getIStudentServiceInstance()
{
StudentServiceImpl ssi = new StudentServiceImpl();
//通过Proxy来创建IStudentService代理对象,newProxyInstance方法第二个参数是被代理实现类的接口数组
//所以JDK的动态代理必须基于接口,不能基于类进行代理
IStudentService service = (IStudentService)Proxy.newProxyInstance(ssi.getClass().getClassLoader(),
ssi.getClass().getInterfaces(), new MyInvocationHandler(ssi));
return service;
}
}
运行结果:
befor execute method:findStudent
可以在这里添加一些前置操作....
findStudent method....
after execute method:findStudent
可以在这里添加一些后置操作....
*****************************
befor execute method:findStudentNum
可以在这里添加一些前置操作....
findStudentNum method ...
after execute method:findStudentNum
可以在这里添加一些后置操作....
从输出的打印信息中可以看出,在使用得到的代理对象执行具体的方法时,会在方法执行前后执行我们在InvocationHandler实现类中添加的前置或后置实现代码。这样的操作可以运用在我们在执行业务操作的方法前添加一些监视代码,达到监视程序运行状况的效果。很多业务场景都可以用到,比如在Spring的AOP中就使用了JDK的动态代理。