说说代理--静态代理
说说代理,
从静态代理,到动态代理,再到AOP的过程。
那什么是静态代理呢?
假如我们有一个需求:给原有的方法添加日志输出
假设我们有一个类Student,一个学生类,他有2个方法,唱歌、跳舞
public class Student { public void sing(){ System.out.println("唱歌。。。"); } public void dance(){ System.out.println("跳舞。。。"); } }
现在有一个需求,就是给每个方法执行前后都加上日志输出,该怎么做?
1.直接修改:
public class Student { public void sing(){ System.out.println("begin..."); System.out.println("唱歌。。。"); System.out.println("end..."); } public void dance(){ System.out.println("begin..."); System.out.println("跳舞。。。"); System.out.println("end..."); } }
上面的方案存在着问题:
1.直接修改程序,不符合开闭原则(何为开闭原则,可以查看设计模式之六大原则这篇博客:https://www.cnblogs.com/takeyblogs/p/14037592.html)。应该对扩展开放,对修改关闭;
2.如果Student类有成千上百个方法,我们得手动一个个去添加,太累了。
3.存在重复代码(都是在核心方法前后打印日志);
4.存在硬编码,不利于后期维护:比如你辛辛苦苦把成千上百个方法都添加了日志输出,之后,你需求又变了,不需要日志输出了,又得一个个去删除。
所以,这种在方法前后手动添加日志输出的方案,不符合。
静态代理:
什么是静态代理?
代理:是一种模式,提供对目标类的间接访问方式,即通过代理访问目标对象。这样就可以在目标实现的基础上增加额外的操作功能,前拦截,后拦截等操作。如图:
举个例子:你想要去买一件东西,这是你叫了另一个人帮你去买(代理),你完全可以不动声色的等他帮你买回来,而太需要去坐地铁,走路,最后送到你手里。
说明:客户访问代理对象,代理对象去访问目标对象。在此当中,代理对象可以做额外的操作,而不修改目标对象。来达到前拦截,后拦截等效果。
常用的的代理模式有:静态代理和动态代理。先来讲讲静态代理
静态代理的实现方式:编写一个代理类,代理对象实现一个接口(这个接口也是目标对象实现的接口),并在内部维护一个目标对象的引用。通过构造器将目标对象
注入进来。在代理对象中调用目标对象的同名方法,并添加拦截。
1.创建一个接口:
public interface Person { public void sing(); public void dance(); }
2.创建一个接口的实现类(目标类)
public class Student implements Person{ public void sing(){ System.out.println("唱歌。。。"); } public void dance(){ System.out.println("跳舞。。。"); } }
3.创建代理对象的实现类(代理类)
public class StudentProxy implements Person { private Student student; public StudentProxy(Student student){ this.student = student; } public void sing() { System.out.println("begin..."); student.sing(); System.out.println("end..."); } public void dance() { System.out.println("begin..."); student.dance(); System.out.println("end..."); } }
4。测试类
public class Test { public static void main(String[] args) { Person person = new StudentProxy(new Student()); person.sing(); person.dance(); } }
5.结果:
原理图如下:
静态代理的优点,就是可以不改变目标对象,代理目标对象进行其他操作。可是还是存在着弊端:
1.直接修改程序,不符合开闭原则。应该对扩展开放,对修改关闭;(解决)
2.如果Student类有成千上百个方法,我们得手动一个个去添加,太累了。(无法解决)
3.存在重复代码(都是在核心方法前后打印日志);(无法解决)
4.存在硬编码,不利于后期维护:比如你辛辛苦苦把成千上百个方法都添加了日志输出,之后,你需求又变了,不需要日志输出了,又得一个个去删除。
所以,这种在方法前后手动添加日志输出的方案,不符合。(无法解决)
静态代理引出来的问题:
我们可以发现每一个代理类的构造方法维护的只有一种类型的目标对象。那如果有多中目标类型需要去代理的话,就得一个一个的去写代理类。
现在有一个新的需求:就是把整个项目的所有方法的前后都加上日志的打印,那简直是要累死人了。
就如下图:
由上图我们可以发现,代理的结构都是一样的,那我们能不能让JVM帮我们去做操作呢,我们只需要传入一个接口,让JVM自动帮我们去生成代理对象。
答案就可以的。让我们来看看动态代理。详情请看下文:https://www.cnblogs.com/takeyblogs/p/14046299.html