栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

代理设计模式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

代理设计模式

生活中的代理设计模式

代理设计模式优点

将通用性的工作都交给代理对象完成,被代理对象只专注自己的核心业务。
1.被代理类中只用关注核心业务的实现,将通用的管理型逻辑(事务管理,日志管理)和业务逻辑分离。
2.将通用的代码放在代理类中实现,提高了代码的复用性
3.通过在代理类添加业务逻辑,实现对原有业务逻辑的扩展(增强)

静态代理

静态代理,代理类只能够为特定的类生产代理对象,不能代表任意类

GenaraDAO
public interface GenaraDAO {
    public void insert();
    public void delect();
    public void update();
}
StaticProxy(代理类)
public class StaticProxy {
    private GenaraDAO genaraDAO;
    public StaticProxy(GenaraDAO genaraDAO) {
        this.genaraDAO = genaraDAO;
    }
    public void insert(){
        begin();
        genaraDAO.insert();
        commmit();
    }
    public void delete(){
        begin();
        genaraDAO.delect();
        commmit();
    }
    public void update(){
        begin();
        genaraDAO.update();
        commmit();
    }
    public void begin(){
        System.out.println("-------开启事务");
    }
    public void commmit(){
        System.out.println("-------提交事务");
    }
}
StudentDAO(被代理类)
public class StudentDAO implements GenaraDAO{
    @Override
    public void insert() {
        System.out.println("-------添加学生");
    }

    @Override
    public void delect() {
        System.out.println("-------删除学生");
    }

    @Override
    public void update() {
        System.out.println("-------更新学生信息");
    }
}
BookDAO(被代理类)
@Override
    public void insert() {
        System.out.println("-------添加书籍");
    }

    @Override
    public void delect() {
        System.out.println("-------删除书籍");
    }

    @Override
    public void update() {
        System.out.println("-------更新书籍信息");
    }

#####Test

@Test
    public void test1(){
        //被代理对象
        BookDAO b![请添加图片描述](https://img-blog.csdnimg.cn/84b781e7967641f89f6a37bf738d7929.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAd3d3d2FudGluZw==,size_20,color_FFFFFF,t_70,g_se,x_16)
ookDAO = new BookDAO();
        //为被代理对象创建代理对象
        StaticProxy proxy = new StaticProxy(bookDAO);
        proxy.delete();
    }
动态代理

动态代理,几乎可以为所有的类产生代理对象
动态代理的实现方式有两种:
1.JDK动态代理
2.CGLib动态代理

JDK动态代理

JDK动态代理:是通过被代理对象实现的接口产生其代理对象
1.创建一个类实现InvocationHandler接口,重写invoke方法
2.在类中定义一个Object类型的变量,并提供这个变量的有参构造器,用于将被代理对象传递进来
3.创建getProxy方法,用于创建并返回代理对象

JDKDynamicProxy
//JDK动态代理:是通过被代理对象实现的接口产生其代理对象
//1.创建一个类实现InvocationHandler接口,重写invoke方法
//2.在类中定义一个Object类型的变量,并提供这个变量的有参构造器,用于将被代理对象传递进来
//3.创建getProxy方法,用于创建并返回代理对象
public class JDKDynamicProxy implements InvocationHandler{
    //被代理对象
    private Object obj;

    public JDKDynamicProxy(Object obj) {
        this.obj = obj;
    }


    //产生代理对象,返回代理对象
    public Object getProxy(){
        //1.获取被代理对象的类加载器
        ClassLoader classLoader = obj.getClass().getClassLoader();
        //2.获取被代理对象的类实现的接口
        Class[] interfaces = obj.getClass().getInterfaces();
        //3.产生代理对象
        //第一个参数是被代理对象的类加载器
        //第二个参数是被代理对象实现的接口
        //第三个参数是产生代理对象调用方法时,用于拦截方法执行的拦截器

        Object o = Proxy.newProxyInstance(classLoader, interfaces,this);
        return o;
    }

    @Override
    //method就是调用的方法
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        begin();
        Object returnValue = method.invoke(obj);
        commit();
        return returnValue;
    }

    public void begin(){
        System.out.println("-------开始事务");
    }
    public void commit(){
        System.out.println("-------提交事务");
    }
}
Test
@Test
    public void test2(){
        //被代理对象
        BookDAO bookDAO = new BookDAO();
        //创建动态代理对象,并将被代理对象传递到道理对象中,赋值给obj
        //proxy就是BookDAO的代理对象:可以强转成被代理对象的接口类型
       GenaraDAO proxy = (GenaraDAO)new JDKDynamicProxy(bookDAO).getProxy();
       //代理对象调用方法,并不会执行调用的方法,而是进入到创建代理对象时指定的InvocationHandler中的invoke方法
        //调用的方法作为一个Method参数,传递给了invoke方法
       proxy.delect();
    }

由于JDK动态代理是通过被代理类实现的接口来创建代理对象的,因此JDK动态代理,只能代理实现了接口的类的对象。如果一个类没有实现任何接口,我们应该使用CGLib代理

CGLib动态代理

CGLib动态代理,是通过创建被代理类的子类来创建代理对象的,因此即使没有实现任何接口的类也可以通过CGLib产生代理对象。
CGLib动态代理不能为final类创建代理对象

添加CGLib的依赖

            cglib
            cglib
            3.3.0
        
CGLib动态代理实现
//1.添加cglib依赖
//2.创建一个类实现MethodInterceptor接口,同时实现接口中的intercept方法
//3.在类中定义一个Object类型的变量,并提供这个变量的有参构造器,用于传递被代理对象
//4.定义getProxy方法进行传递返回代理对象(代理对象是通过 创建被代理类的子类来创建的)
public class CGLibDynamicProxy implements MethodInterceptor {
    private Object obj;
    public CGLibDynamicProxy(Object obj) {
        this.obj = obj;
    }

    //产生代理的过程
    public Object getProxy(){
        Enhancer enhancer = new Enhancer();
        //把被代理对象设为父类
        enhancer.setSuperclass(obj.getClass());
        enhancer.setCallback(this);
        Object proxy = enhancer.create();

        return proxy;
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        begin();
        Object returenValue = method.invoke(obj,objects);//通过反射调用被代理类的方法
        commit();
        return returenValue;
    }
    public void begin(){
        System.out.println("-------开始事务");
    }
    public void commit(){
        System.out.println("-------提交事务");
    }
}
Test
@Test
public void test3(){
    //创建被代理对象
    BookDAO bookDAO = new BookDAO();

    //创建代理对象
    CGLibDynamicProxy cgLibDynamicProxy = new CGLibDynamicProxy(bookDAO);
    //代理对象实际上是被代理对象的子类,因此代理对象可以直接被强转为代理类型
    BookDAO proxy = (BookDAO) cgLibDynamicProxy.getProxy();
    //使用代理对象调用方法,实际上并没有执行这个方法,而是执行了代理类中的intercept方法,将当前调用的方法,以及方法中的参数传递到intercept方法
    proxy.update();
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/582155.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号