代理模式能够有效的将具体实现与调用进行解耦,经过面向接口进行编码彻底将具体的实现隐藏在内部。html
代理实现的通常模式:定义一个接口,而后建立具体的实现类实现这个接口,建立一个代理类还实现这个接口,具体的实现类须要把接口中定义的方法的业务逻辑实现,而代理类中的方法只要调用实现类中的对应方法便可。以后咱们须要使用接口中的某个方法的功能时直接调用代理类的方法就能够了,将具体的实现类隐藏在底层。ide
静态代理和动态代理的区别:主要是代理类的建立不一样。静态代理是咱们在编译以前就直接实现与代理类相同的接口,直接在实现的方法中调用实现类的相应方法就能够了。而动态代理不一样,咱们不知道何时建立,建立针对哪一个接口,实现类的代理类等。静态代理能够直接编码建立,而动态代理是经过反射机制来抽象出代理类的建立过程。函数
所谓静态代理就是,在编译的时候就将接口、实现类、代理类都手动完成。测试
接口:this
/** * 代理类和被代理类公共的接口 * @author TYX * */ public interface Person { //上交班费 void getMoney(); }
具体实现类:编码
/** * 定义一个被代理的类,继承公共接口 * @author TYX * */ public class Student implements Person { private String name; public Student(String name) { super(); this.name = name; } @Override public void getMoney() { System.out.println("上交班费50元"); } }
代理类:spa
/** * 静态代理在程序运行以前已经编译好了。 * 代理类,类中定义一个被代理类的实体,还有代理的行为 * @author TYX * */ public class StudentProxy implements Person { //定义一个被代理类的对象 Student student; //这个构造器传入的是一个接口的对象 public StudentProxy(Person student2) { //只代理student这个类 if(student2.getClass() == Student.class){ this.student = (Student) student2; } } //代理上交班费 @Override public void getMoney() { /*代理类就是在访问实际对象时引入的必定程度的间接性,正是因为这种间接性,能够附加不少种 用途间接性就是指不直接调用对象的方法,那么咱们在代理过程当中加上一些其余的用途,使用用代理就能够轻松办到 * */ System.out.println("最近这位同窗表现很好哦~");//在一个切点以前能执行一些别的操做这就是AOP中的特色。也能够在调用代理类以后进行操做。 student.getMoney(); } }
测试类:代理
public class TestStaticProxy { public static void main(String[] args) { //定义一个学生对象 Person student = new Student("张三"); //生成代理对象,并将学生对象传给代理对象 Person moniter = new StudentProxy(student); //班长代理上交班费 moniter.getMoney(); } }
结果htm
最近这位同窗表现很好哦~
上交班费50元对象
动态代理:代理类在运行时因需实时建立。
接口:
public interface Person { //上交班费 void getMoney(); }
具体实现类
/** * 定义一个被代理的类,继承公共接口 * @author TYX * */ public class Student implements Person { private String name; public Student(String name) { super(); this.name = name; } //定义一个方法执行时间的方法 @Override public void getMoney() { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("上交班费50元"); } }
代理类
/** * 动态代理实现 * 类中有一个被代理类的实例,全部执行代理对象的方法都会被替换成执行invock方法 * @author TYX * */ public class StudentProxyHandler<T> implements InvocationHandler { //定义一个被代理类的对象 private T targe; public StudentProxyHandler(T targe) { super(); this.targe = targe; } /** * proxy 是被代理对象(实例) * method 正在执行的方法 * args 调用目标方法时传入的实参 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("代理执行" + method.getName() + "方法"); MonitorUtil.start(); Object result = method.invoke(targe, args); MonitorUtil.finish(method.getName()); return result; } public Object proxyInstance(){ return Proxy.newProxyInstance(targe.getClass().getClassLoader(), targe.getClass().getInterfaces(), this); } }
测试类
/** * 建立一个动态代理对象的步骤 * 1. 建立一个与代理对象向关联的invocationHandler InvocationHandler stuHandler = new StudentProxyHandler<Person>(student1); 2. 使用Proxy类的getProxyClass静态方法生成一个动态代理类的stuProxyClass Class<?> stuProxyClass = Proxy.getProxyClass(Person.class.getClassLoader(), Person.class.getInterfaces()); 3. 得到stuProxyClass 中一个带InvocationHandler参数的构造器cnstructor Constructor<?> constructor = stuProxyClass.getConstructor(InvocationHandler.class); 4. 构造器Constructor来建立一个动态实例 Person stuProxy = (Person) constructor.newInstance(stuHandler); * @author TYX * */ public class TestDynamicProxy { public static void main(String[] args) throws NoSuchMethodException, SecurityException { // Person student = new Student("张三"); //建立一个被代理类的实例对象 Person student1 = new Student1("李四"); //建立一个与代理对象向关联的invocationHandler InvocationHandler stuHandler = new StudentProxyHandler<Person>(student1); //建立一个代理对象stuProxy来代理被代理类的实例,代理对象的每一个执行方法都会替换执行invocation中的invock方法 Person stuProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler); //代理执行上交班费的方法 stuProxy.getMoney(); /*Person student1 = new Student1("李四"); //建立一个与代理对象向关联的invocationHandler StudentProxyHandler stuHandler = new StudentProxyHandler<Person>(student1); //建立一个代理对象stuProxy来代理被代理类的实例,代理对象的每一个执行方法都会替换执行invocation中的invock方法 Person stuProxy = (Person) stuHandler.proxyInstance(); //代理执行上交班费的方法 stuProxy.getMoney();*/ } }
结果
代理执行getMoney方法
交做业喽
getMoney方法耗时2000ms
总结:
1.首先要建立接口,jdk代理是基于接口实现的。
2.建立一个有代理对象关联的invocationHandler,重写invocationHandler 接口里的invock()方法
3.经过Proxy.newProxyInstance建立一个代理对象。
4.用代理对象调用方法
接下来看一下cglib动态代理的实现:https://www.cnblogs.com/mr-long/p/5889054.html
jdk动态代理须要实现接口,当须要代理的类没有实现接口时cglib代理是一个很好的选择。可是被代理类中的final方法,没法进行代理,由于子类中没法重写final函数