所谓代理模式就是不是自己执行自己的方法,而是找别的类来代替自己调用自己的方法,这就是静态代理:
下面是借鉴他人的例子,首先感谢大佬的深情讲解,就是说我是一个程序员(Programmer),但是我能够写代码,但是我写的代码是主要用于发布博客,那我写的博客没有人来看,我就想找大V来给我点赞,这样我就能引流过来一些用户,来看我的文章—这个过程中,是大V发布文章,我去写,最终是大V代表着我去发布,很像枪手对吧;

静态代理

  1. //我需要别人代理的方法
  2. public interface Programmer {
  3. // 程序员每天都写代码发布文章
  4. void coding();
  5. }
  6. //我
  7. public class Java3y implements Programmer {
  8. @Override
  9. public void coding() {
  10. System.out.println("我发布了最新文章:......给女朋友讲解什么是代理模式.......");
  11. }
  12. }
  13. //大V
  14. public class ProgrammerBigV implements Programmer {
  15. // 指定程序员大V要让谁发文章(先发文章、后点赞)
  16. private Java3y java3y ;
  17. public ProgrammerBigV(Java3y java3y) {
  18. this.java3y = java3y;
  19. }
  20. // 程序员大V点赞评论收藏转发
  21. public void upvote() {
  22. System.out.println("程序员大V点赞评论收藏转发!");
  23. }
  24. @Override
  25. public void coding() {
  26. // 让Java3y发文章
  27. java3y.coding();
  28. // 程序员大V点赞评论收藏转发!
  29. upvote();
  30. }
  31. }
  32. //运行
  33. public class Main {
  34. public static void main(String[] args) {
  35. // 想要发达的Java3y
  36. Java3y java3y = new Java3y();
  37. // 受委托程序员大V
  38. Programmer programmer = new ProgrammerBigV(java3y);
  39. // 受委托程序员大V让Java3y发文章,大V(自己)来点赞
  40. programmer.coding();
  41. }
  42. }

经过一段时间后,得这是一条财路。于是就给足了程序员大V钱,让程序员大V只做他的生意,不能做其他人的生意(断了其他人的财路)。
于是乎,程序员大V做Java3y一个人的生意:

透明代理(普通代理)

  1. public class ProgrammerBigV implements Programmer {
  2. // 指定程序员大V要给Java3y点赞
  3. private Java3y java3y ;
  4. // 只做Java3y的生意了
  5. public ProgrammerBigV() {
  6. this.java3y = new Java3y();
  7. }
  8. // 程序员大V点赞评论收藏转发
  9. public void upvote() {
  10. System.out.println("程序员大V点赞评论收藏转发!");
  11. }
  12. @Override
  13. public void coding() {
  14. // 让Java3y发文章了
  15. java3y.coding();
  16. // 程序员大V点赞评论收藏转发!
  17. upvote();
  18. }
  19. }
  20. //程序员大V想要赚点零花钱的时候直接让Java3y发文章就好了。
  21. public class Main {
  22. public static void main(String[] args) {
  23. // 受委托程序员大V
  24. Programmer programmer = new ProgrammerBigV();
  25. // 受委托程序员大V让Java3y发文章,大V来点赞
  26. programmer.coding();
  27. }
  28. }
  29. //此时,真实对象(Java3y)对外界来说是透明的。

这样就实现了我发文章,但是大V其实做了包装,让我有钱可赚了;但是时间一长,大V就觉得我的流量上去了有了利用价值;
PS:加钱感觉不好,毕竟这个操作需要原对象的参与,除非给原对象加一个金额数比如说—-一个亿;
这就是代理类添加的自定义方法

代理类自定义方法

  1. public class ProgrammerBigV implements Programmer {
  2. // ..省略了上面的代码
  3. // 添加广告吧
  4. public void addAdvert() {
  5. System.out.println("这次我要加广告");
  6. }
  7. @Override
  8. public void coding() {
  9. // 让Java3y发文章了
  10. java3y.coding();
  11. // 程序员大V点赞评论收藏转发!
  12. upvote();
  13. // 加广告
  14. addAdvert();
  15. }
  16. }

这里可以说是对代理对象的附能,让原本只能写代码的程序员java3y能,附带广告,从而大家一起赚钱;

动态代理

随着找时间的推移,程序员感觉自己的知识和本事都被大V砍掉了一部分,所以程序员觉得有必要改变方式了,于是就开始请水军来点赞支持;
如果是水军的话就不能自己去构建代理对象了,这个时候JDK的Proxy对象,这个类可以使用反射来构建代理对象;

  1. public class Main {
  2. public static void main(String[] args1) {
  3. // Java3y请水军
  4. Java3y java3y = new Java3y();
  5. Programmer programmerWaterArmy = (Programmer) Proxy.newProxyInstance(
  6. java3y.getClass().getClassLoader(),
  7. java3y.getClass().getInterfaces(),
  8. (proxy, method, args) -> {
  9. // 如果是调用coding方法,那么水军就要点赞了
  10. if (method.getName().equals("coding")) {
  11. method.invoke(java3y, args);
  12. System.out.println("我是水军,我来点赞了!");
  13. } else {
  14. // 如果不是调用coding方法,那么调用原对象的方法
  15. return method.invoke(java3y, args);
  16. }
  17. return null;
  18. });
  19. // 每当Java3y写完文章,水军都会点赞
  20. programmerWaterArmy.coding();
  21. }
  22. }

这样写真实方便
接下来看看这个Proxy类,
设计模式-代理模式 - 图1

loader:就是被代理的对象的classoader,
interfaces:就是被代理的对象实现的接口,表示我需要代理这对象的哪个部分;
h:你要做什么事情,当然这里肯定是拦截的接口interfaces里面所有的方法,你需要通过method去区分;

注意!!!!:总结一下代理模式必须要有的几个因素
1)代理对象有跟目标对象相同的方法,
2)使用代理必须要有接口,
3)动态代理是通过反射调用invoke方法来实现代理,且肯定会用到Proxy对象;

区别!!!!:静态代理需要自己写代理类(代理类需要实现与目标对象相同的接口),动态代理不需要自己编写代理类;

静态代理的弊端(动态代理的好处):
静态代理时如果目标对象有多个方法,我们的代理类必须一一实现,这样需要改动代码;动态代理是使用jdk的Proxy类实例化代理对象,通过反射机制默认就实现了接口的全部方法;

其他方式的动态代理

目前动态代理也可以不实现接口,这样的代理方式称为——cglib代理:
忽略导包,版本3.2.5
直接上代码:

  1. public class HelloService {
  2. public HelloService() {
  3. System.out.println("HelloService构造");
  4. }
  5. /**
  6. * 该方法不能被子类覆盖,Cglib是无法代理final修饰的方法的
  7. */
  8. final public String sayOthers(String name) {
  9. System.out.println("HelloService:sayOthers>>"+name);
  10. return null;
  11. }
  12. public void sayHello() {
  13. System.out.println("HelloService:sayHello");
  14. }
  15. }
  16. //自定义MethodInterceptor:主要是为类添加“======插入前置通知======”
  17. import net.sf.cglib.proxy.MethodInterceptor;
  18. import net.sf.cglib.proxy.MethodProxy;
  19. import java.lang.reflect.Method;
  20. public class MyMethodInterceptor implements MethodInterceptor{
  21. /**
  22. * sub:cglib生成的代理对象
  23. * method:被代理对象方法
  24. * objects:方法入参
  25. * methodProxy: 代理方法
  26. */
  27. @Override
  28. public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  29. System.out.println("======插入前置通知======");
  30. Object object = methodProxy.invokeSuper(sub, objects);
  31. System.out.println("======插入后者通知======");
  32. return object;
  33. }
  34. }
  35. import net.sf.cglib.core.DebuggingClassWriter;
  36. import net.sf.cglib.proxy.Enhancer;
  37. public class Client {
  38. public static void main(String[] args) {
  39. // 代理类class文件存入本地磁盘方便我们反编译查看源码
  40. System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");
  41. // 通过CGLIB动态代理获取代理对象的过程
  42. Enhancer enhancer = new Enhancer();
  43. // 设置enhancer对象的父类
  44. enhancer.setSuperclass(HelloService.class);
  45. // 设置enhancer的回调对象
  46. enhancer.setCallback(new MyMethodInterceptor());
  47. // 创建代理对象
  48. HelloService proxy= (HelloService)enhancer.create();
  49. // 通过代理对象调用目标方法
  50. proxy.sayHello();
  51. }
  52. }

运行结果:
设计模式-代理模式 - 图2
以上代码和图片转自:CGLIB动态代理实现原理
感谢大佬!!
然后大佬后面还跟了源码分析,如果想看的话还是去那边看吧,这里就不再啰嗦了;
总结归纳:
cglib方式的代理其实就是通过反射鼓捣出了一个代理类,然后通过该代理类进行相关操作