设计模式--代理模式

代理模式:

       对被代理的对象提供一种代理以控制对于对象的访问,代理对象可以控制对于对象的访问,在不改变目标对象的基础上添加额外的功能。

      场景:(1)远程访问的对象 (2)创建开销很大的对象 (3)需要安全控制的对象(4)AOP(面向切面编程)(5)事务(6)权限管理

      特点:

    (1)具有两种主体:代理对象、被代理对象

    (2)对于被代理对象,事情是必须要去做的,但是自己不想去做,或者没有条件去做,所有需要由代理对象去完成。

    (3)代理对象能够获取被代理对象的资料,代码层面(能够获得被代理对象的引用)

      生活中的案例:

     (1)中介:通常买二手车的时候,会去网上找车源,对车进行质量检测,以及各种过户手续的办理,自己可能不想做这些事情,所以可以找第三方的中介公司来完成这些事情,我只负责把我想要的车辆的信息(价位、车辆新旧程度、品牌)反馈给中介,中介把所有的办好就只管我来签字验收就可以了。

    (2)黄牛:当春运火车票比较紧张的时候,我抢不到票,且自己也不想去抢,则可以通过黄牛去买,我只管把我的车票信息给他(初始地、目的地、出发时间、车次),由此不用抢票,也可以买到相应的车票,抢票的过程由黄牛去做。

    (3)媒人:平时自己没有时间去交女朋友,则需要媒人去介绍,我们只管把我们想要的女朋友的类型给媒人,媒人则帮我们去寻找合适的对象。

      代理分为两种

      (1)静态代理:在编译前,已经把代码创建好,程序运行时,class文件已经存在

      (2)动态代理:程序运行时,运用反射机制动态生成代理类

静态代理实现:

接口

public interface IUser {
    void add();

    void delete();
}

具体实现类

public class UserImps implements IUser {
    public void add() {
        System.out.println("add");
    }
    public void delete() {
        System.out.println("delete");
    }
}

代理类

public class UserProxy implements IUser {
    private  IUser iUser;
    public UserProxy(IUser iUser){
        this.iUser = iUser;
    }
    public void add() {
        System.out.println("before");
        iUser.add();
        System.out.println("after");
    }

    public void delete() {
        System.out.println("before");
        iUser.delete();
        System.out.println("after");
    }
}

      由代码可以看出:代理类和实现类持有相同的接口,并且代理类持有具体实现类的引用,调用代理类相当于调用实现类,由此可以在代理类执行相应的增强代码。

缺点:

(1)不够灵活,每个代理类只为一个接口服务。会造成大量的代码重复

(2)静态代理类只为特定的接口服务,如果有多个接口,则要生成多个代理对象,不利于系统维护。

动态代理(关心过程):

      动态代理的字节码类在程序运行时运用反射机制动态生成,不用手工写代码

动态代理类的实现

代理类

public class CarAgency implements InvocationHandler{

    //被代理对象的引用
    private Object target;

    //获取被代理对象的信息,为被代理对象生成代理对象
    public Object getInstanche(Object target){
        this.target = target;
        Class clazz = target.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(),target.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("办理车辆质量检查报告");
        method.invoke(target,args);
        System.out.println("办理车辆二手车过户");
        return null;
    }
}

接口类:

public interface CustomerService {
    void bugCar();
}

接口实现类

public class CustomerServiceImpl implements CustomerService {
    @Override
    public void bugCar() {
        System.out.println("决定就买这辆车了");
    }
}

通过以上的步骤就可以实现一个动态代理,但是动态代理的原理是怎样的呢

原理:

     (1)代理类拿到被代理类的引用,获取相应的接口信息

运行时生成class的条件:(1)提供一组interface (2)相应的类加载器  (3)生成proxy不处理实际工作,需要传入一个handler,由handler负责实际的工作

动态代理处于reflect包下,

(1)InvocationHandler:

InvocationHandler 接口为方法调用接口,它声明了负责调用任意一个方法的invoke()方法。(InvocationHandler 是代理实例的调用处理程序实现的接口。invoke()在代理实例上处理方法调用并返回结果

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

proxy:动态代理类实例
method:要调用的方法
args:要调用的参数 

 

(2)Proxy(提供创建动态代理类 和 实例的静态方法)

getProxyClass() 提供动态代理类

 

public static Class<?> getProxyClass(ClassLoader loader, Class<?>[] interfaces) throws IllegalArgumentException
loader:动态代理的类加载器
interfaces:动态代理要实现的所有接口
<strong>newProxyInstance()(负责创建动态代理类的实例)

</strong>

 

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler) throws IllegalArgumentException

InvocationHandler h:InvocationHandler接口的子类的实例

 

interfaces:动态代理要实现的所有接口
loader:动态代理的类加载器 接口: 
public interface DynamicHelloWorld { String hello(); }

实现类:

public class DynamicHelloWorldImps implements DynamicHelloWorld {
    public String hello() {
        System.out.println("hello world");
        return "hello world";
    }
}

动态代理类(实现invocationhandler)

public class DynamicProxy implements InvocationHandler {
    //真实对象的引用
    private Object target;

    public DynamicProxy(Object target) {
        //持有对真实对象的引用
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before dynamicProxy");
        //反射机制调用目标类的方法
        method.invoke(target, args);
        System.out.println("after dynamicProxy");
        return null;
    }
}

测试类

public static void main(String[] args) {
    DynamicHelloWorld dynamicHelloWorld = new DynamicHelloWorldImps();
    InvocationHandler ih = new DynamicProxy(dynamicHelloWorld);
    //根据proxy和业务处理逻辑 生成一个代理对象
    DynamicHelloWorld dhw = (DynamicHelloWorld) Proxy.newProxyInstance(DynamicHelloWorld.class.getClassLoader(),new Class<?>[]{DynamicHelloWorld.class},ih);
    dhw.hello();
}

 


CGlib动态代理:
CGlib是针对类实现的,采用继承的方式为目标类生成子类,覆盖父类的方法,对方法进行增强,不能对final的类进行代理。
CGlib通过字节码的技术为一个类创建子类,在子类中采用方法拦截的形式拦截所有父类方法的调用,顺势插入横切逻辑。
具体实现类

 

 

public class userImpl {
    public void say(){
        System.out.println("这是一个测试");
    }
}

动态代理类:

 

 

public class userCglibProxy implements MethodInterceptor {

    private Object target;

    public Object getInstance(Object target){
        this.target = target;
        Enhancer enhancer = new Enhancer();
        //传入目标类
        enhancer.setSuperclass(target.getClass());
        //设置回调
        enhancer.setCallback(this);
        //返回代理对象
        return enhancer.create();
    }

    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before");
        Object obj = methodProxy.invokeSuper(o,objects);
        System.out.println("after");
        return obj;
    }
}

测试类:

 

 

public class test {
    public static void main(String[] args) {
        userCglibProxy proxy = new userCglibProxy();
        userImpl obj = (userImpl)proxy.getInstance(new userImpl());
        obj.say();
    }
}


JDK动态代理和CGlib动态代理是实现Spring AOP的基础。Spring对于两者进行结合使用,实现Spring AOP。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值