1.相关概念
- 1.1 代理
在某些情况下,我们不希望或是不能直接访问对象 A,而是通过访问一个中介对象 B,由 B 去访问 A 达成目的,这种方式我们就称为代理。
这里对象 A 所属类我们称为委托类,也称为被代理类,对象 B 所属类称为代理类。
代理优点有:
隐藏委托类的实现
解耦,不改变委托类代码情况下做一些额外处理,比如添加初始判断及其他公共操作
根据程序运行前代理类是否已经存在,可以将代理分为静态代理和动态代理。
- 1.2 静态代理
代理类在程序运行前已经存在的代理方式称为静态代理。
通过上面解释可以知道,由开发人员编写或是编译器生成代理类的方式都属于静态代理,如下是简单的静态代理实例:
class ClassA {
public void operateMethod1() {};
public void operateMethod2() {};
public void operateMethod3() {};
}
public class ClassB {
private ClassA a;
public ClassB(ClassA a) {
this.a = a;
}
public void operateMethod1() {
a.operateMethod1();
};
public void operateMethod2() {
a.operateMethod2();
};
// not export operateMethod3()
}
上面ClassA是委托类,ClassB是代理类,ClassB中的函数都是直接调用ClassA相应函数,并且隐藏了Class的operateMethod3()函数。
静态代理中代理类和委托类也常常继承同一父类或实现同一接口。
* 1.3 动态代理
代理类在程序运行前不存在、运行时由程序动态生成的代理方式称为动态代理。
Java 提供了动态代理的实现方式,可以在运行时刻动态生成代理类。这种代理方式的一大好处是可以方便对代理类的函数做统一或特殊处理,如记录所有函数执行时间、所有函数执行前添加验证判断、对某个特殊函数进行特殊操作,而不用像静态代理方式那样需要修改每个函数。
A:动态代理概述
- 代理:本来应该自己做的事情,请了别人来做,被请的人就是代理对象。
- 举例:春节回家买票让人代买
- 动态代理:在程序运行过程中产生的这个对象,而程序运行过程中产生对象其实就是反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理
- 在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib,Proxy类中的方法创建动态代理类对象
动态代理实例
实现动态代理包括三步:
- 新建委托类;
- 实现InvocationHandler接口,这是负责连接代理类和委托类的中间类必须实现的接口;
- 通过Proxy类新建代理类对象。
- proxy中的方法
- public static Object newProxyInstance()
- 最终会调用InvocationHandler的方法
- InvocationHandler接口
- public Object invoke(Object proxy,Method method,Object[] args);
//step1: 定义User接口 public interface User { public void add(); public void delete(); } //step2: 定义类实现User接口 public class UserImp implements User { @Override public void add() { //System.out.println("权限校验"); System.out.println("添加功能"); //System.out.println("日志记录"); } @Override public void delete() { //System.out.println("权限校验"); System.out.println("删除功能"); //System.out.println("日志记录"); } } //step3: InvocationHandler的实现类 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("权限校验"); method.invoke(target, args); //执行被代理target对象的方法 System.out.println("日志记录"); return null; } } //定义测试类 import java.lang.reflect.Proxy; public class Test { /** * @param args */ public static void main(String[] args) { /*UserImp ui = new UserImp(); ui.add(); //添加功能 ui.delete(); //删除功能 System.out.println("-------------------------------");*/ /* * public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, * InvocationHandler h) */ /* MyInvocationHandler m = new MyInvocationHandler(ui); User u = (User)Proxy.newProxyInstance(ui.getClass().getClassLoader(), ui.getClass().getInterfaces(), m); u.add(); //权限校验 添加功能 日志记录 u.delete(); //权限校验 删除功能 日志记录 */ StudentImp si = new StudentImp(); si.login();//登录 si.submit();//提交 System.out.println("-------------------------------"); MyInvocationHandler m = new MyInvocationHandler(si); Student s = (Student)Proxy.newProxyInstance(si.getClass().getClassLoader(), si.getClass().getInterfaces(), m); s.login(); //权限校验 登录 日志记录 s.submit(); //权限校验 提交 日志记录 } } //类似step1: 定义Student接口 public interface Student { public void login(); public void submit(); } //类似step2: 定义类实现Student接口 public class StudentImp implements Student { @Override public void login() { System.out.println("登录"); } @Override public void submit() { System.out.println("提交"); } }