java 反射的另外一个主题是动态代理。
关于代理的概念,如果不是太理解,可以先查询参考下设计模式中的代理。
[b]代理的简单概念:[/b]
[b]抽象主题[/b]:一个接口
[b]真实实现主题[/b]:真实实现主题的类
[b]代理实现主题[/b]:首先实现和真实主题一样的抽象主题接口,在其中可以调用真实主题的方法。[b]一般代理实现主题都会有一个真实主题的组合成员。[/b]
动态代理的概念:
可以动态的根据真实主题和抽象主题 生成代理实现主题,因为可以动态不特定的生成,故曰:动态代理。
java 中的代理实现:
jvm通过动态 解析字节码的形式,动态生成代理主题。
jdk提供的支持类:
1、java.lang.reflect.InvocationHandler 调用接口
是[b]代理实例[/b]的[b]调用处理程序[/b] 实现的接口。每个代理实例都具有一个关联的[b]调用处理程序[/b]。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的[b]调用处理程序的 invoke 方法[/b]。
此接口的唯一方法:
Object invoke(Object proxy, //代理对象(在其上调用方法的代理实例)
Method method,// 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
Object[] args) //真实主题传递给method的参数
throws Throwable
2、java.lang.reflect.Proxy 代理工厂类(以下引用JDK描述)
主要方法介绍:
1、public static InvocationHandler getInvocationHandler(Object proxy) 返回指定代理实例的调用处理程序。
2、public static boolean isProxyClass(Class<?> cl)
当且仅当指定的类通过 getProxyClass 方法或 newProxyInstance 方法动态生成为代理类时,返回 true。
3、public static Object newProxyInstance(ClassLoader loader, //定义代理类的类加载器
Class<?>[] interfaces, //代理类要实现的接口列表
InvocationHandler h)指派方法调用的调用处理程序
throws IllegalArgumentException
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
下面举例说明动态代理:
1、抽象主题
2、真实主题
3、调用处理程序
4、测试代码
输出:
before ->method.invoke
[wangxinchun, 123456]
public abstract java.lang.String com.horizon.reflect.proxy.ILogin.login(java.lang.String,java.lang.String)
end ->method.invoke
success
before ->method.invoke
null
public java.lang.String java.lang.Object.toString()
end ->method.invoke
com.horizon.reflect.proxy.UserLogin@19b49e6
关于代理的概念,如果不是太理解,可以先查询参考下设计模式中的代理。
[b]代理的简单概念:[/b]
[b]抽象主题[/b]:一个接口
[b]真实实现主题[/b]:真实实现主题的类
[b]代理实现主题[/b]:首先实现和真实主题一样的抽象主题接口,在其中可以调用真实主题的方法。[b]一般代理实现主题都会有一个真实主题的组合成员。[/b]
动态代理的概念:
可以动态的根据真实主题和抽象主题 生成代理实现主题,因为可以动态不特定的生成,故曰:动态代理。
java 中的代理实现:
jvm通过动态 解析字节码的形式,动态生成代理主题。
jdk提供的支持类:
1、java.lang.reflect.InvocationHandler 调用接口
是[b]代理实例[/b]的[b]调用处理程序[/b] 实现的接口。每个代理实例都具有一个关联的[b]调用处理程序[/b]。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的[b]调用处理程序的 invoke 方法[/b]。
此接口的唯一方法:
Object invoke(Object proxy, //代理对象(在其上调用方法的代理实例)
Method method,// 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
Object[] args) //真实主题传递给method的参数
throws Throwable
2、java.lang.reflect.Proxy 代理工厂类(以下引用JDK描述)
主要方法介绍:
1、public static InvocationHandler getInvocationHandler(Object proxy) 返回指定代理实例的调用处理程序。
2、public static boolean isProxyClass(Class<?> cl)
当且仅当指定的类通过 getProxyClass 方法或 newProxyInstance 方法动态生成为代理类时,返回 true。
3、public static Object newProxyInstance(ClassLoader loader, //定义代理类的类加载器
Class<?>[] interfaces, //代理类要实现的接口列表
InvocationHandler h)指派方法调用的调用处理程序
throws IllegalArgumentException
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
下面举例说明动态代理:
1、抽象主题
package com.horizon.reflect.proxy;
/**
* 抽象主题
* @author create by <a href="xinchunwang@aliyun.com">新春.王</a> <br>
* date :Apr 20, 2013 6:10:10 PM
*/
public interface ILogin {
public String login(String username, String password);
}
2、真实主题
package com.horizon.reflect.proxy;
/**
* 真实实现主题
* @author create by <a href="xinchunwang@aliyun.com">新春.王</a> <br>
* date :Apr 20, 2013 6:10:48 PM
*/
public class UserLogin implements ILogin {
@Override
public String login(String username, String password) {
// TODO Auto-generated method stub
return "success";
}
}
3、调用处理程序
package com.horizon.reflect.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* 调用处理程序
* @author create by <a href="xinchunwang@aliyun.com">新春.王</a> <br>
* date :Apr 20, 2013 6:23:38 PM
*/
public class LoginInvocationHandler implements InvocationHandler {
private ILogin login;
public LoginInvocationHandler(ILogin login){
this.login = login;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object obj= null;
System.out.println("before ->method.invoke");
System.out.println(Arrays.toString(args));
System.out.println(method);
obj = method.invoke(login, args);
System.out.println("end ->method.invoke");
return obj;
}
}
4、测试代码
package com.horizon.reflect.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* 动态代理测试
*
* @author create by <a href="xinchunwang@aliyun.com">新春.王</a> <br>
* date :Apr 20, 2013 6:11:30 PM
*/
public class LoginTest {
public static void main(String[] args) {
//Proxy.getProxyClass(LoginTest.class.getClassLoader(), ILogin.class);
InvocationHandler h = new LoginInvocationHandler(new UserLogin());
ILogin obj = (ILogin)Proxy.newProxyInstance(LoginTest.class.getClassLoader(), new Class[]{ILogin.class}, h);
System.out.println(obj.login("wangxinchun", "123456"));
System.out.println(obj);
}
}
输出:
before ->method.invoke
[wangxinchun, 123456]
public abstract java.lang.String com.horizon.reflect.proxy.ILogin.login(java.lang.String,java.lang.String)
end ->method.invoke
success
before ->method.invoke
null
public java.lang.String java.lang.Object.toString()
end ->method.invoke
com.horizon.reflect.proxy.UserLogin@19b49e6