设计模式-代理模式

代理模式概念

在这里插入图片描述

代理模式示例图

在这里插入图片描述

静态代理

  1. 代理对象和目标对象的共同接口
package com.proxy;

public interface Teacher {

    public  void teach();
}
  1. 目标对象
package com.proxy;

public class Teacher_1 implements Teacher{

    @Override
    public void teach() {
        System.out.println("老师正在上课");
    }
}

  1. 代理对象
package com.proxy;

public class Teacher_1_proxy implements Teacher {
    public Teacher teacher;
    public Teacher_1_proxy(Teacher teacher) {
        this.teacher = teacher;
    }

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

  1. 客户端
package com.proxy;

public class Client {
    public static void main(String[] args) {
        Teacher teacher = new Teacher_1();
        Teacher_1_proxy teacher_1_proxy = new Teacher_1_proxy(teacher);
        teacher_1_proxy.teach();
    }

}

静态代理优缺点

在这里插入图片描述

动态代理

在这里插入图片描述
示例:
待实现的接口:

package com.jdk;
public interface Teacher {
    public void teach(String name,int age);
    public  void rest();
}

接口的具体实现类:

package com.jdk;
public class TargetTeacher implements Teacher{

    @Override
    public void teach(String name,int age) {
        System.out.println(name+"开始授课"+",她的年龄是"+age);
    }

    @Override
    public void rest() {
        System.out.println("老师休息");
    }
    public void newTeach(String name,int age) {
        System.out.println(name+"开始授课"+",她的年龄是"+age+",新teach");
    }
}

代理工厂,用于生成代理类:

package com.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//代理工厂,用于生成代理对象
public class ProxyFactory {
    //用于代理的目标对象
    public Object target;

    public ProxyFactory(Object o) {
        this.target = o;
    }
    //获取代理对象的方法
    public  Object getProxy() {
        /*
           1.第一个参数:目标对象的类加载器
           2.第二个参数:目标对象实现的接口
           3.第三个参数:InvocationHandler接口,代理对象的实际的代理过程,即添加额外功能和调用目标对象方法的地方
         */
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            /*
                1.proxy:代理对象
                2.method:代理对象要执行的方法的描述,这个参数传入的是抽象接口中的方法
                3.args:代理对象执行的方法传入的实际参数,这个参数是要作为method中描述的方法的传入参数
             */
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("代理对象:"+proxy.getClass());
                System.out.println("方法:"+method.getDeclaringClass().getName()+","+method.getClass());
                for(Object o:args) {
                    System.out.print(o.toString()+",");
                }
                System.out.println("开始代理");
                 //触发具体实现类中的的method描述的方法,args作为参数传入
                Object returnval =  method.invoke(target,args);
                return returnval;
            }
        });
    }
}

测试类:

package com.jdk;
import java.lang.reflect.Field;
public class Client {
    public static void main(String[] args) {

        Teacher t = new TargetTeacher();
        ProxyFactory proxyFactory = new ProxyFactory(t);
        /*这里不能强制转换成接口的实现类,必须是接口,这是因为代理类实现了接口,
        所以返回的代理对象其实是接口的"子对象",因此代理对象不能执行接口实现类的特有方法
        TargetTeacher proxy = (TargetTeacher) proxyFactory.getProxy();
        proxy.newTeach("fan",22);会执行出错
         */
        Teacher proxy = (Teacher) proxyFactory.getProxy();
        proxy.teach("fan",22);
        //proxy.rest();

    }
}

动态代理的执行过程:

  1. 动态代理类是在程序运行时生成的,其继承了Proxy类并且实现了目标对象实现的接口
  2. 代理类利用反射机制生成了四个Method对象,这四个对象分别是equals,hashCode,toString和代理类将要执行的方法的描述信息。
  3. 代理类重写上述四个方法,重写过程是调用父类Proxy中的invoke方法,并将对应的Method对象作为参数传入。
    详细过程请参考下面相关链接。
    相关参考:
    反射及动态代理原理

cglib代理

在这里插入图片描述
在这里插入图片描述
示例:

目标对象类:

package com.cglib;

public class TeacherDao {
    public void teach(){
        System.out.println("我是cglib");
    }
}

生成代理对象的类:

package com.cglib;


import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class ProxyFactory implements MethodInterceptor {
    //目标对象,被代理的对象
    private Object target;
    public ProxyFactory(Object o) {
        this.target = o;
    }
    //返回代理对象
    public Object getProxy() {
        //1.创建工具类
        Enhancer enhancer = new Enhancer();
        //2.设置父类
        enhancer.setSuperclass(target.getClass());
        //3.设置回调函数
        enhancer.setCallback(this);
        //4、创建子类对象,即代理对象
        return enhancer.create();
    }

    @Override
    //方法拦截器,当调用方法时就会对方法进行拦截
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("代理开始");
        Object returnval = method.invoke(target,args);
        System.out.println("代理结束");
        return returnval;
    }
}

测试类:

package com.cglib;

public class Client {
    public static void main(String[] args) {
        TeacherDao teacherDao = new TeacherDao();
        ProxyFactory proxyFactory = new ProxyFactory(teacherDao);
        TeacherDao t = (TeacherDao) proxyFactory.getProxy();
        //调用方法时会被拦截,从而执行拦截器中的代码
        t.teach();
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值