代理模式

代理模式属于结构型的模式,通过代理对象来访问目标对象,即可以扩展目标对象的功能,比如日志记录,或者是安全检查,我们常用的AOP面向切面编程是属于一种代理模式。

代理模式的形式:静态代理,动态代理(JDK 代理),cglib代理(基于内存实现)

代理模式的角色

  • 客户端:通过代理对象访问目标对象
  • 代理对象
  • 目标对象

代理模式(静态代理,动态代理,cglib代理)-LMLPHP

静态代理

代理对象与目标对象都要实现同一个接口或者父类,客户端通过代理对象来访问目标对象

案例

代理模式(静态代理,动态代理,cglib代理)-LMLPHP

代码

抽象父类接口


/**
 *  抽象父类接口
 *
 * @author: Hui
 **/
public interface ITeacher {

    public void teach();

}

目标对象
/**
 *  目标对象
 *
 * @author: Hui
 **/
public class TeacherTarget implements ITeacher{
    @Override
    public void teach() {
        System.out.println(" 老师开始授课了 ~~~~");
    }
}
代理对象
/**
 *  代理对象
 *
 * @author: Hui
 **/
public class TeacherProxy implements ITeacher{

    private ITeacher iteacher;

    public TeacherProxy(ITeacher teacher) {
        this.iteacher = teacher;
    }

    @Override
    public void teach() {
        System.out.println("代理对象  开始");
        iteacher.teach();
        System.out.println("代理对象  结束");
    }
}

客户端使用
/**
 * 客户端
 *
 * @author: Hui
 **/
public class Client {

    public static void main(String[] args) {

        TeacherTarget teacherTarget = new TeacherTarget();

        TeacherProxy teacherProxy = new TeacherProxy(teacherTarget);

        teacherProxy.teach();
    }
}

输出结果

代理模式(静态代理,动态代理,cglib代理)-LMLPHP

动态代理

又称为 JDK 代理,通过JDK 反射的包来实现。

案例

代理模式(静态代理,动态代理,cglib代理)-LMLPHP

代码

抽象父类与实现类

/**
 * 抽象父类
 *
 */
public interface ITeacher {

    void teach();
}

/**
 *  目标对象
 *
 * @author: Hui
 **/
public class TeacherDao implements ITeacher{
    @Override
    public void teach() {
        System.out.println("老师授课中 ~~~~");
    }
}
代理工厂
/**
 *  代理工厂
 *
 * @author: Hui
 **/
public class ProxyFactory {

    private Object target;

    //构造器
    public ProxyFactory(Object target){
        this.target = target;
    }

    //获取代理对象
    public Object getProxyInstance(){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("开始代理");
                Object resultVal = method.invoke(target, args);
                System.out.println("结束代理");
                return resultVal;
            }
        });
    }
}
客户端
/**
 *  客户端
 *
 * @author: Hui
 **/
public class Client {

    public static void main(String[] args) {

        ITeacher teacherDao = new TeacherDao();
        // 创建代理对象
        ITeacher proxyFactory = (ITeacher) new ProxyFactory(teacherDao).getProxyInstance();

        proxyFactory.teach();
    }
}

cglib代理

cglib代理是可以不急于抽象父类或者抽象接口。

使用的代理工厂实现methodIntecetor,重写 intecetor方法就可以了。

引入依赖

       <!-- https://mvnrepository.com/artifact/cglib/cglib -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.5</version>
        </dependency>

目标对象

/**
 *  目标对象
 *
 * @author: Hui
 **/
public class TeacherTarget {

    public void teach()
    {
        System.out.println("老师授课中...");
    }

}

代理工厂

/**
 *  代理工厂
 *
 * @author: Hui
 **/
public class ProxyFactory implements MethodInterceptor {

    private Object target;

    public Object getProxyInstance(Object obj){
        this.target = obj;
        //1.创建工具类
        Enhancer enhancer = new Enhancer();
        //2.设置父类
        enhancer.setSuperclass(obj.getClass());
        //3.设置回调函数
        enhancer.setCallback(this);
        //4.创建子类对象,即代理对象
        Object proxyObj = enhancer.create();
        //返回代理对象
        return proxyObj;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("cglib代理开始");
        Object resultVal = method.invoke(target, objects);
        System.out.println("cglib代理结束");
        return resultVal;
    }
}

客户端

/**
 *  客户端
 *
 * @author: Hui
 **/
public class Client {
    public static void main(String[] args) {

        ProxyFactory proxyFactory = new ProxyFactory();

        TeacherTarget teacherProxy =(TeacherTarget) proxyFactory.getProxyInstance(new TeacherTarget());

        teacherProxy.teach();

    }
}
07-14 11:55