为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。

    【三种实现形式】

    • 静态代理:要求被代理对象需要实现接口或继承父类,我们的代理对象与被代理对象一起实现相同的接口或继承相同父类。
    • JDK动态代理:通过Jdk自带的Proxy类来实现,原理是实现了被代理对象的接口。要求被代理对象需要实现接口,但是我们的代理对象不需要实现接口。
    • Cglib动态代理:也叫子类代理,通过额外引用Cglib包来实现,原理是继承了被代理对象。对被代理对象没有什么要求,不需要实现接口或继承父类。

    【代理模式(静态)VS 装饰模式】

    • 相同点:都需要实现同一个接口或者继承同一个抽象类,并且代理角色和装饰角色都持有被代理角色和构件角色的引用。
    • 不同点:代理模式重点在于控制对象的行为,而装饰模式侧重于增加对象的职能。通俗的讲,它们俩根本的区别是目的性不一样,也就是使用场景。

      1. /**
      2. * 老师
      3. */
      4. public interface Teacher {
      5. void teach();
      6. }
      1. /**
      2. * 老师 实现类
      3. */
      4. public class TeacherImpl implements Teacher {
      5. @Override
      6. public void teach() {
      7. System.out.println("老师开始讲课...");
      8. }
      9. }

      【静态代理】

      1. /**
      2. * 老师 - 静态代理类
      3. */
      4. public class TeacherStaticProxy implements Teacher {
      5. private Teacher teacher;
      6. public TeacherStaticProxy(Teacher teacher) {
      7. this.teacher = teacher;
      8. }
      9. @Override
      10. public void teach() {
      11. System.out.println("[静态代理]上课前起立");
      12. teacher.teach();
      13. System.out.println("[静态代理]下课后起立");
      14. }
      15. }

      【JDK动态代理】

      1. /**
      2. * 老师 - JDK动态代理类
      3. */
      4. public class TeacherDynamicProxy {
      5. private Teacher teacher;
      6. public TeacherDynamicProxy(Teacher teacher) {
      7. this.teacher = teacher;
      8. }
      9. public Teacher getProxy() {
      10. return (Teacher) Proxy.newProxyInstance(teacher.getClass().getClassLoader(), teacher.getClass().getInterfaces(), new InvocationHandler() {
      11. @Override
      12. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      13. System.out.println("[JDK动态代理]上课前起立");
      14. Object obj = method.invoke(teacher, args);
      15. System.out.println("[JDK动态代理]下课后起立");
      16. return obj;
      17. }
      18. });
      19. }
      20. }

      【Cglib动态代理】

      1. /**
      2. * 老师 - Cglib动态代理类
      3. */
      4. public class TeacherCglibProxy implements MethodInterceptor {
      5. private Teacher teacher;
      6. public TeacherCglibProxy(Teacher teacher) {
      7. this.teacher = teacher;
      8. }
      9. public Teacher getProxy() {
      10. // 1. 使用Enhancer创建代理类
      11. Enhancer enhancer = new Enhancer();
      12. // 2. 继承被代理类
      13. enhancer.setSuperclass(teacher.getClass());
      14. // 3. 设置回调
      15. enhancer.setCallback(this);
      16. // 4. 生成代理对象
      17. return (Teacher) enhancer.create();
      18. }
      19. @Override
      20. public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
      21. System.out.println("[Cglib动态代理]上课前起立");
      22. Object obj = method.invoke(teacher, objects);
      23. System.out.println("[Cglib动态代理]下课后起立");
      24. return obj;
      25. }
      26. }

    1. public class ProxyTest {
    2. public static void main(String[] args) {
    3. Teacher teacher = new TeacherImpl();
    4. // 静态代理
    5. TeacherStaticProxy staticProxy = new TeacherStaticProxy(teacher);
    6. staticProxy.teach();
    7. System.out.println();
    8. // JDK动态代理
    9. TeacherDynamicProxy dynamicProxy = new TeacherDynamicProxy(teacher);
    10. dynamicProxy.getProxy().teach();
    11. System.out.println();
    12. // Cglib动态代理
    13. TeacherCglibProxy cglibProxy = new TeacherCglibProxy(teacher);
    14. cglibProxy.getProxy().teach();
    15. }
    16. }
    17. ----输出----
    18. [静态代理]上课前起立
    19. 老师开始讲课...
    20. [静态代理]下课后起立
    21. [JDK动态代理]上课前起立
    22. 老师开始讲课...
    23. [JDK动态代理]下课后起立
    24. [Cglib动态代理]上课前起立
    25. 老师开始讲课...
    26. [Cglib动态代理]下课后起立