代理模式详细讲解

文章目录

  • 一、什么是代理模式?
  • 二、 为什么使用代理模式?
  • 三、 代理模式的实现
    • 1、静态代理
      • 1.1、 创建公共的接口
      • 1.2、 创建被代理角色
      • 1.3、 创建代理角色
      • 1.4、 创建测试类
    • 2、动态代理的实现
      • 2.1、 使用 JDK 的 Proxy 类实现动态代理
        • 1、 创建业务接口
        • 2、 创建接口实现类
        • 3、 创建生成代理对象的工厂
        • 4、 创建切面对象
        • 5、 创建测试类
      • 2.2、 使用 CGLIB 实现动态代理
        • 1、添加 jar 包
        • 2、 创建业务接口
        • 3、创建接口实现类
        • 4、创建生成代理对象的工厂
        • 5、 创建切面
        • 6、 创建测试类


一、什么是代理模式?

代理模式(Proxy Pattern):代理模式是 Java 常见的设计模式之一。所谓代理模式是指客户端并不直接调用实际的对象,而是通过调用代理对象,来间接的调用实际的对象。通俗的来讲代理模式就是我们生活中常见的中介。
代理模式详细讲解_第1张图片

二、 为什么使用代理模式?

  • 隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
  • 开闭原则:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。

代理模式的优点:
代理模式详细讲解_第2张图片
代理模式的缺点:
代理模式详细讲解_第3张图片

三、 代理模式的实现

代理模式可以分为两种:静态代理、动态代理。

1、静态代理

静态代理模式由三个部分构成:

  • 一个公共的接口
  • 一个被代理角色
  • 一个代理角色

1.1、 创建公共的接口


//公共接口
public interface Rent {
    void renting();
}

1.2、 创建被代理角色


//被代理对象
public class Corey implements Rent{
    //这是被代理对象!(房主)
    @Override
    public void renting() {
        System.out.println("Corey有房出租");
    }
}

1.3、 创建代理角色

//代理对象(中介)
public class StaticProxyRent implements Rent{
    private Rent rent;

    public StaticProxyRent(Rent rent){
        this.rent = rent;
    }

    @Override
    public void renting() {
        System.out.println("向房客出租房屋");
        this.rent.renting();
        System.out.println("完成售后服务");
    }
}

1.4、 创建测试类

public class StaticProxyTest {
    public static void main(String[] args) {
        Rent rent = new Corey();
        StaticProxyRent staticProxyRent = new StaticProxyRent(rent);
        staticProxyRent.renting();
    }
}

2、动态代理的实现

在动态代理中分为两种实现方式:

  • 使用 JDK 的 Proxy 类实现动态代理
  • 使用 CGLIB 实现动态代理

2.1、 使用 JDK 的 Proxy 类实现动态代理

1、 创建业务接口

public interface JdkProxyRent {
    void renting();
}

2、 创建接口实现类

public class JdkProxyCorey implements JdkProxyRent {
    @Override
    public void renting() {
        System.out.println("Corey 有房出租!");
    }
}

3、 创建生成代理对象的工厂

//动态生成代理对象的工厂
public class JdkProxyFactory {

    //动态生成代理对象
    public static Object getProxyBean(Object target){
        Class clazz = target.getClass();
        MyAspect myAspect = new MyAspect();
        //在JDK中动态生成代理对象的方法
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
            //动态生成代理对象的方法
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                myAspect.before();
                Object obj =  method.invoke(target,args);
                myAspect.after();
                return obj;
            }
        });
    }
}

4、 创建切面对象


public class MyAspect {
    public void before(){
        System.out.println("带领房客看房...签租房协议");
    }
    public void after(){
        System.out.println("售后服务");
    }
}

5、 创建测试类

public class jdkProxyTest {
    public static void main(String[] args) {
        JdkProxyRent jdkProxyRent = new JdkProxyCorey();
        JdkProxyRent jdkProxyRent1 =(JdkProxyRent)JdkProxyFactory.getProxyBean(jdkProxyRent);
        jdkProxyRent1.renting();

    }
}

2.2、 使用 CGLIB 实现动态代理

CGLIB(Code Generation Library)是一个高性能开源的代码生成包,它被许多框架所使用,其底层是通过使用一个小而快的字节码处理框架 ASM(Java 字节码操控框架)转换字节码并生成新的类。因此 CGLIB 要依赖于 ASM 的包。
JDK 的动态代理机制只能代理实现了接口的类,而对于没有实现接口的类就不能使用JDK 的 Proxy 类生成代理对象,cglib 是针对类来实现代理的,他的原理是对指定的目标类生成一个子类并通过回调的方式来实现增强,但因为采用的是继承,所以不能对 final 修饰的类进行代理。

1、添加 jar 包

cglib.jar
asm.jar

2、 创建业务接口

public interface CglibProxyRent {
    void renting();
}

3、创建接口实现类


public class CglibProxyCorey implements CglibProxyRent {
    @Override
    public void renting() {
        System.out.println("Corey 有房出租");
    }
}

4、创建生成代理对象的工厂

public class CglibProxyBeanFactory {
    public static Object getProxyBean(CglibProxyRent rent){
        CglibMyAspect myAspect = new CglibMyAspect();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(rent.getClass());
        enhancer.setCallback(new MethodInterceptor() {

            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                myAspect.before();
                Object obj = method.invoke(rent,objects);
                myAspect.after();
                return obj;
            }
        });
        return enhancer.create();
    }
}

5、 创建切面

public class CglibMyAspect {
    public void before(){
        System.out.println("带领客户看房,签订租房协议");
    }

    public void after(){
        System.out.println("售后服务");
    }
}

6、 创建测试类

public class Test {
    public static void main(String[] args) {
        CglibProxyRent rent = new CglibProxyCorey();
        CglibProxyRent rent1 = (CglibProxyRent) CglibProxyBeanFactory.getProxyBean(rent);
        rent1.renting();
    }
}


你可能感兴趣的:(Spring,代理模式,java,开发语言)