依照代理的创建时期,代理类能够分为两种:
静态代理:
UserManager接口:
public interface UserManager { public void addUser(String userId, String userName); //加入用户方法 public String findUser(String userId); //删除用户方法 }
UserManagerImpl类:
public class UserManagerImpl implements UserManager { //用户加入 public void addUser(String userId, String userName) { try { System.out.println("用户ID" + userId); }catch(Exception e) { e.printStackTrace(); throw new RuntimeException(); } } //用户查询 public String findUser(String userId) { System.out.println("用户ID" + userId); return "张三"; }
UserManagerImplProxy代理类:
private UserManager userManager; //含有目标类对象的引用 public UserManagerImplProxy(UserManager userManager) { this.userManager = userManager; } public void addUser(String userId, String userName) { try { System.out.println("開始加入-->>加入用户ID" + userId); userManager.addUser(userId, userName); System.out.println("成功加入-->>addUser()"); }catch(Exception e) { e.printStackTrace(); System.out.println("加入失败-->>addUser()"); } } public String findUser(String userId) { return null; //此处不实现,若是实现,其方式同add方法 }
client调用:
public class Client { public static void main(String[] args) { UserManager userManager = new UserManagerImplProxy(new UserManagerImpl()); userManager.addUser("0001", "张三"); } }
观察以上代码。能够发现每个代理类仅仅能为一个接口服务(public UserManagerImplProxy(UserManageruserManager))。这样一来须要建立大量的代理类。
而且,全部的代理操作除了调用的方法不一样之外,其它的操作都一样。比如,findUser中若是实现,将反复使用System.out.println("開始加入-->>加入用户ID"+ userId); System.out.println("成功加入-->>addUser()"); System.out.println("加入失败-->>addUser()");反复的代码出现多次对于开发者来说是绝对不同意的,那么该怎么解决问题呢?最好的办法那就是通过一个代理类完毕所有的代理功能,这就涉及到了动态代理。
动态代理:在程序执行时,运用反射机制动态创建而成。
代码演示样例:
UserManager接口:
public interface UserManager { public void addUser(String userId, String userName); public String findUser(String userId); }
真正实现类:
public class UserManagerImpl implements UserManager { public void addUser(String userId, String userName) { try { System.out.println("用户ID" + userId); }catch(Exception e) { e.printStackTrace(); throw new RuntimeException(); } } public String findUser(String userId) { System.out.println("用户ID" + userId); return "张三"; }
动态代理代理类:
public class LogHandler implements InvocationHandler { private Object targetObject; //依据传过来的对象生成代理 public Object newProxyInstance(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 { System.out.println("start-->>" + method.getName()); for (int i=0; i<args.length; i++) { System.out.println(args[i]); } Object ret = null; try { //调用目标方法 ret = method.invoke(targetObject, args); System.out.println("success-->>" + method.getName()); }catch(Exception e) { e.printStackTrace(); System.out.println("error-->>" + method.getName()); throw e; } return ret; } }
动态代理包括一个接口和一个类:
InvocationHandler接口:
Public static Object newProxyInstance(ClassLoader loader,Class<?>[]interfaces,InvocatiocHandler h) throws IllegalArgumentException
返回一个指定接口的代理类实例,该接口能够将方法调用指派到指定的调用处理程序。
參数:
Loader:定义代理类的类载入器
Class<?>[]interfaces:得到所有的接口
InvocationHandlerh:得到InvocationHandler接口的子类实例
Proxy类:动态的声明出一个代理对象,为什么样生成出代理呢?这个类必须实现了接口才行。假设这个类没有实现接口,不能生成代理。说白了他就是依据这个接口在内存中建立出一个类。
client调用:
public class Client { public static void main(String[] args) { LogHandler logHandler = new LogHandler(); UserManager userManager = (UserManager)logHandler.newProxyInstance(new UserManagerImpl()); userManager.addUser("001","猪猪"); } }
总结:
动态代理相对于静态代理来说更加灵活了。为什么呢?比如重载和覆盖。重载属于静态的结构。当定义两个參数不一样的method方法时,我们在调用的时候。须要指定method方法的參数。
也就是我们在编译的时候就指定好该调谁了。而覆盖的功能更强,由于它的方法调用不是静态的时候进行绑定,也不是说我写代码编译的时候就指定好我应该调谁。而是在执行的时候决定它是什么类型就调谁。
正常情况下。我们须要创建非常多的代理类,假设我还有其它的manager也须要完毕这些功能,那么她还须要创建代理类,来完毕。动态代理则不用,由于这个proxySubject这个类不须要自己创建,他在内存中创建。所以你压根就不知道代理类的存在。当然代理类的个数。也不须要你关心。