方便起见, 根据孙鑫的一个例子来学习,先看代码:
ILogin接口
public
interface
ILogin
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
public boolean login(String username,String password);
}
ILogin接口的实现类(即被代理类):
public
class
LoginAction
implements
ILogin
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
public boolean login(String username,String password)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if("zhangsan".equals(username))
throw new RuntimeException();
else if("lisi".equals(username) && "1234".equals(password))
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
return true;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
return false;
}
}
}
代理类:
import
java.lang.reflect.InvocationHandler;
import
java.lang.reflect.Method;
import
java.lang.reflect.Proxy;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
import
org.apache.commons.logging.Log;
import
org.apache.commons.logging.LogFactory;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
public
class
LoginHandler
implements
InvocationHandler
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
private Object targetObject;
Log log=LogFactory.getLog(LoginHandler.class);
public Object bind(Object targetObject)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
this.targetObject=targetObject;
return Proxy.newProxyInstance(
targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),
this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if(ILogin.class.isAssignableFrom(targetObject.getClass()))
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
String username=(String)args[0];
String methodName=method.getName();
if("login".equals(methodName))
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
log.info("user" + " ["+username+"] is logining");
boolean bFlag=(Boolean)method.invoke(targetObject,args);
if(bFlag)
log.info("user" + " ["+username+"] login success");
else
log.info("user" + " ["+username+"] login failed");
return bFlag;
}
}
return method.invoke(targetObject,args);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
测试方法:
public
void
testDynamicProxy()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
LoginHandler handler=new LoginHandler();
ILogin login=(ILogin)handler.bind(new LoginAction());
login.login("zhangsan","1234");
}
实现一个动态代理类,首先要实现InvocationHandler接口,这个接口只有一个invoke方法:
Object invoke(Object proxy,Method method,Object[] args)
throws
Throwable
参数解释:
proxy:代理对象,
method:对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
args:包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。
接着,还要写一个方法用于绑定被代理对象,方法的名字可以自己定义,这里为bind:
public
Object bind(Object targetObject)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
this.targetObject=targetObject;
return Proxy.newProxyInstance(
targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),
this);
}
说一下Proxy的newProxyInstance静态方法:(这种方法是为被代理对象创建一个代理对象,这种产生代理的方法是动态的,所以称作动态代理)
public
static
Object newProxyInstance(ClassLoader loader,Class
<?>
[] interfaces, InvocationHandler h)
throws
IllegalArgumentException
参数:
loader:被代理对象的类加载器,以加载代理对象。
interfaces:被代理对象实现的接口 h:指派方法调用的调用处理程序
这种方法只能对接口进行代理,如果被代理类的方法在接口里没有定义,则这个方法不能被代理执行。
一个代理对象调用一个方法(Ilogin接口里的任何一个方法)的时候,实现InvocationHandler的类的invoke的方法首先被调用,如果不同的方法需要代理的功能都不同(本例的代理功能是添加登录验证),那就需要在invoke方法里做判断,这样使用代理就没有什么优势了。