关键接口描述
Proxy 提供了用于创建动态代理类和代理对象的静态方法
,它也是所有动态代理类的父类。
接口 | 描述 |
---|---|
static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) | 返回代理类的 java.lang.Class 对象,并向其提供类加载器,该代理类将实现interface所指定的接口 |
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) | 返回一个指定接口的代理类实例(即直接创建一个动态代理对象),该代理对象的实现类实现了interfaces中接口,执行代理对象的每个方法都会被换执行InvocationHandler 对象的invoke 方法 |
注意:第一种生成了动态代理类之后,如果需要通过该代理类来创建对象,依然需要传入一个InvocationHandler对象
。 系统生成的每个代理对象都有一个与之关联的InvocationHandler对象
。
动态代理类实现都必须要先提供InvocationHandler
这个接口的实现类,并且每个代理类的实例都关联到了一个handler
,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler
这个接口的invoke
方法来进行调用。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
loader:
一个ClassLoader对象,定义了由哪个ClassLoader
对象来对生成的代理对象进行加载interfaces:
一个Interface
对象的数组,表示的是要给需要代理的对象提供一组什么接口,如果提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样就能调用这组接口中的方法了h:
一个InvocationHandler
对象,表示的是当这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象
上
案例分析
案例一
package myDynamicProxy;
/**
* 动态代理通过动态代理直接创建一个代理对象实例
*/
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 第一步: 被代理的接口
*/
interface Person {
void walk();
void speak();
}
/**
*
* 第二步:创建一个具体的实现类(真正的被代理的角色--真实对象/角色)
*/
class Man implements Person {
@Override
public void walk() {
System.out.println("a man is walking!");
}
@Override
public void speak() {
System.out.println("a man is speaking!");
}
}
/**
* 创建Handler,需要重写invoke()方法; 通过代理对象调用一个方法的时候,
* 这个方法的调用就会被转发为由InvocationHandler这个接口的invoke方法来进行调用
*/
class PersonInvocationHandler implements InvocationHandler {
//这个就是我们要代理的真实对象
private Object target;
public PersonInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName() + "执行前");
//具体的代理对象
//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
method.invoke(target, args);
System.out.println(method.getName() + "执行后");
return null;
}
}
public class MyDyNamicProxy {
public static void main(String[] args) {
// 我们要代理的真实对象
Person person = new Man();
//代理哪个真实对象,就将该对象传进去
InvocationHandler handler = new PersonInvocationHandler(person);
//使用指定的InvocationHandler来生成一个动态代理对象
//生成代理对象的API,Proxy.newProxyInstance(...);
Person p = (Person) Proxy.newProxyInstance(
Person.class.getClassLoader(),
new Class[]{Person.class}, handler);
//推荐使用上面一种,因为Person的字节码在JVM只存在一份。
/* Person p = (Person) Proxy.newProxyInstance(
person.getClass().getClassLoader(),
new Class[]{person.getClass()}, handler);*/
p.walk();
System.out.println(p.getClass().getName());//myDynamicProxy.$Proxy0 (在运行是动态生成的一个对象)
}
}
可以将
PersonInvocationHandler
看做代理类,通过Proxy.newProxyInstance(...)
生成代理对象。
案例二
继续使用上面的真实对象;简化实现过程。
package myDynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理工厂
*/
public class ProxyFactory {
//真实对象;需要被代理的对象
public Object target;
public ProxyFactory(Object target) {
this.target = target;
}
//获取代理对象
public Object getInstanceProxy() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName() + "执行前");
Object returnValue = method.invoke(target,args);
System.out.print(method.getName() + "执行后");
return returnValue;
}
});
}
}
class Client {
public static void main(String[] args) {
Person person = new Man();
Person p = (Person)new ProxyFactory(person).getInstanceProxy();
p.walk();
}
}
其他案例(测试类,可略过)
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
public class ProxyTest {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
System.out.println(clazzProxy1.getName());//com.sun.proxy.$Proxy0
System.out.println("----------begin constructors list----------");
Constructor[] constructors = clazzProxy1.getConstructors();
for(Constructor constructor : constructors){
String name = constructor.getName();
StringBuilder sBuilder = new StringBuilder(name);
sBuilder.append('(');
Class[] clazzParams = constructor.getParameterTypes();
for(Class clazzParam : clazzParams){
sBuilder.append(clazzParam.getName()).append(',');
}
if(clazzParams!=null && clazzParams.length != 0)
sBuilder.deleteCharAt(sBuilder.length()-1);
sBuilder.append(')');
System.out.println(sBuilder.toString());
}
System.out.println("----------begin methods list----------");
Method[] methods = clazzProxy1.getMethods();
for(Method method : methods){
String name = method.getName();
StringBuilder sBuilder = new StringBuilder(name);
sBuilder.append('(');
Class[] clazzParams = method.getParameterTypes();
for(Class clazzParam : clazzParams){
sBuilder.append(clazzParam.getName()).append(',');
}
if(clazzParams!=null && clazzParams.length != 0)
sBuilder.deleteCharAt(sBuilder.length()-1);
sBuilder.append(')');
System.out.println(sBuilder.toString());
}
System.out.println("----------begin create instance object----------");
Constructor constructor = clazzProxy1.getConstructor(InvocationHandler.class);
class MyInvocationHander1 implements InvocationHandler{
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return null;
}
}
Collection proxy1 = (Collection)constructor.newInstance(new MyInvocationHander1());
System.out.println(proxy1);
proxy1.clear();
//是因为size()要返回一个整数,而在invoke中返回了一个null,null无法转换成整数。其中clear本身就返回void
//proxy1.size();
Collection proxy2 = (Collection)constructor.newInstance(new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return null;
}
});
final ArrayList target = new ArrayList();
Collection proxy3 = (Collection)getProxy(target,new MyAdvice());
proxy3.add("zxx");
proxy3.add("lhm");
proxy3.add("bxd");
System.out.println(proxy3.size());
System.out.println(proxy3.getClass().getName());
}
private static Object getProxy(final Object target,final Advice advice) {
Object proxy3 = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler(){
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 proxy3;
}
}