一、代理概念
为某个对象提供一个代理,以控制对这个对象的访问。代理类和委托类有共同的父类或父接口,代理类负责请求的预处理,过滤,将请求分配给委托类处理。
二、静态代理:
由程序员创建或工具生成代理类的源码,再编译代理类,即代理类和委托类的关系再程序运行前就已经存在。现有一User接口,对user的增删改查,User的实现里面分别有对每个方法的安全性检查,使用静态代理实现:
UserManager:
package com.bjpowernode.spring;
public interface UserManager {
public void addUser(String username, String password);
public void delUser(int userId);
public String findUserById(int userId);
public void modifyUser(int userId, String username, String password);
}
UserManagerImpl:
package com.bjpowernode.spring;
public class UserManagerImpl implements UserManager {
public void addUser(String username, String password) {
<span style="color:#ff0000;">checkSecurity();</span>
System.out.println("---------UserManagerImpl.add()--------");
}
public void delUser(int userId) {
<span style="color:#ff0000;">checkSecurity();</span>
System.out.println("---------UserManagerImpl.delUser()--------");
}
public String findUserById(int userId) {
<span style="color:#ff0000;">checkSecurity();</span>
System.out.println("---------UserManagerImpl.findUserById()--------");</span>
<span style="font-size:18px;">return "张三";
}
public void modifyUser(int userId, String username, String password) {
<span style="color:#ff0000;">checkSecurity();</span>
System.out.println("---------UserManagerImpl.modifyUser()--------");
}
private void <span style="color:#cc0000;">checkSecurity()</span> {
System.out.println("-------checkSecurity-------");
}
}
UserManagerImplProxy:
package com.bjpowernode.spring;
public class UserManagerImplProxy implements UserManager {
//目标对象
private UserManager userManager;
//通过构造方法传入目标对象
publicUserManagerImplProxy (UserManager userManager){
this.userManager=userManager;
}
public void addUser(String username, String password) {
try{
//添加打印日志的功能
//开始添加用户
System.out.println("start-->addUser()");
userManager.addUser(userId, userName);
//添加用户成功
System.out.println("success-->addUser()");
}catch(Exception e){
//添加用户失败
System.out.println("error-->addUser()"); }
}
public void delUser(int userId) {
userManager.delUser(userId);
}
public String findUserById(int userId) {
userManager.findUserById(userId);
return"张三";
}
public void modifyUser(int userId, String username, String password) {
userManager.modifyUser(userId,userName);
}
}
可以看出,如果对User每个方法进行安全性验证,存在两个问题:一、在User的实现类中每个方法中都要调用,客户端如果测试,直接new一个UserManagerImpl。二、每个代理类只能实现一个接口,如果业务复杂,就会产生许多的代理类,所以想办法通过一个代理类完成全部代理功能,动态代理出现。java中实现动态代理机制,需要java.lang.reflect.InvocationHandler 接口和 java.lang.reflect.Proxy 类的支持。
三、动态代理
java.lang.reflect.InvocationHandler接口的定义如下:
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
Object proxy:被代理的对象
Method method:要调用的方法
Object[] args:方法调用时所需要参数
java.lang.reflect.Proxy类的定义如下:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
CLassLoader loader:类的加载器
Class<?> interfaces:得到全部的接口
InvocationHandler h:得到InvocationHandler接口的子类的实例
UserManagerImpl,其中UserManager同上:
package com.bjpowernode.spring;
public class UserManagerImpl implements UserManager {
public void addUser(String username, String password) {
System.out.println("---------UserManagerImpl.add()--------");
}
public void delUser(int userId) {
System.out.println("---------UserManagerImpl.delUser()--------");
}
public String findUserById(int userId) {
System.out.println("---------UserManagerImpl.findUserById()--------");
return "张三";
}
public void modifyUser(int userId, String username, String password) {
System.out.println("---------UserManagerImpl.modifyUser()--------");
}
}
SecurityHandler实现:
package com.bjpowernode.spring;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class SecurityHandler implements InvocationHandler {
private Object targetObject;
public Object createProxyInstance(Object targetObject) {
this.targetObject = targetObject;//取得代理对象
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(),
this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
checkSecurity();
//调用目标方法
Object ret = method.invoke(targetObject, args);
return ret;
}
private void checkSecurity() {
System.out.println("-------checkSecurity-------");
}
}
Client调用:
package com.bjpowernode.spring;
public class Client {
public static void main(String[] args) {
SecurityHandler hander = new SecurityHandler();
UserManager useraManager = (UserManager)hander.createProxyInstance(new UserManagerImpl());
useraManager.addUser("张三", "123");
}
}
这样可以看出,动态代理把散落在程序角落的方法都放在一个类里面。它始终无法摆脱仅支持 interface 代理的桎梏,因为它的设计注定了这个遗憾。回想一下那些动态生成的代理类的继承关系图,它们已经注定有一个共同的父类叫 Proxy。Java 的继承机制注定了这些动态代理类们无法实现对 class 的动态代理,原因是多继承在 Java 中本质上就行不通。