一、动态代理引入
package cn2; public interface IUserDAO { /** * 登录方法 */ public void login(); /** * 注册方法 */ public void register(); } package cn2; public class UserDAOImpl implements IUserDAO { @Override public void login() { System.out.println("用户登录"); } @Override public void register() { System.out.println("用户注册"); } } package cn2; public class Test { public static void main(String[] args) { IUserDAO dao = new UserDAOImpl(); dao.register(); dao.login(); } }
用户注册
用户登录
如果我要给每个方法都增加权限校验和日志记录的话,那么代码实现如下:
package cn2; public interface IUserDAO { /** * 登录方法 */ public void login(); /** * 注册方法 */ public void register(); } package cn2; public class UserDAOImpl implements IUserDAO { @Override public void login() { System.out.println("用户登录"); } @Override public void register() { System.out.println("用户注册"); } } package cn2; public class UserDAOImpl2 implements IUserDAO { private void actionCheck(){ System.out.println("权限检查"); } private void record(){ System.out.println("日志记录"); } @Override public void login() { this.actionCheck(); System.out.println("登录"); this.record(); } @Override public void register() { this.actionCheck(); System.out.println("注册"); this.record(); } } package cn2; public class Test { public static void main(String[] args) { IUserDAO dao = new UserDAOImpl2(); dao.register(); dao.login(); } }
权限检查
注册
日志记录
权限检查
登录
日志记录
为什么要单独写一个类去实现接口,并增加权限校验和日志记录呢?因为我们在设计的时候,要保证对扩展功能开发,对修改代码关闭的原则。我定义了一个新的类去实现接口,就是想扩展原来接口的功能,而不是在原有的实现类上修改。
但是,如果都这样设计,是很可怕的事情,如果需求一旦变更,那我们需要定义好多好多的实现类,太复杂了。怎么办?
在生活中,我们会遇到很多问题,比如:我要租房子,但是我不认识房东,怎么办?找中介。同样的道理,我自己不想在修改代码去增加权限检查和日志记录的功能,那么我找一个代理对象去帮我实现不就可以了吗?
动态代理:就是在程序运行过程中产生的这个对象。
在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口接可以生成动态代理对象。JDK只针对接口做代理。
Proxy类中的方法创建动态代理对象
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
最终会调用InvocationHandler的方法
Object invoke(Object proxy,Method method,Object[] args)
package cn2; public interface IUserDAO { /** * 登录方法 */ public void login(); /** * 注册方法 */ public void register(); } package cn2; public class UserDAOImpl implements IUserDAO { @Override public void login() { System.out.println("用户登录"); } @Override public void register() { System.out.println("用户注册"); } } package cn2; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target) { this.target = target; } /** *返回动态代理对象 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("权限检查"); Object invoke = method.invoke(target, args); System.out.println("日志记录"); return invoke; } } package cn2; import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { //使用动态代理之前 IUserDAO dao = new UserDAOImpl(); dao.register(); dao.login(); System.out.println("-------------------"); //使用动态代理之后 IUserDAO proxy = (IUserDAO)Proxy.newProxyInstance(dao.getClass().getClassLoader(), dao.getClass().getInterfaces(), new MyInvocationHandler(dao)); proxy.register(); proxy.login(); } }
用户注册
用户登录
-------------------
权限检查
用户注册
日志记录
权限检查
用户登录
日志记录