JAVA代理详记

一、什么叫做代理?

代理模式是JAVA设计模式中的一种,作用是创建一个与委托类实现同样的接口代理类,为委托类提供预处理消息、过滤消息、转发消息至委托类、以及处理结尾等功能。代理类与委托类是一对一的,并且代理类并不真正实现服务,而是通过将消息转发给委托类的相关方法来实现服务的提供。通俗易懂一点就是我们是通过调用代理对象来访问的实际对象,而代理对象可以在调用实际对象的前后或途中进行功能的扩展。
在这里插入图片描述

二、为什么要使用代理?

1、客户端可能无法直接操作对象(在另一台机器),那么可以在客户端建立一个代理对象,然后客户端直接调用目标对象,代理对象在与目标对象建立联系

2、需要加强目标对象的功能。有人表示为什么不在当初的类中加好,要使用代理来补充。单一职责要求一个类的功能尽可能单一,而且增强的功能大多都是与之前业务不同,比如增加日志输出,权限判断等,本来就不应该由之前的类去承担

三、代理的实现?

1、静态代理

是由程序员开发时写在源码中并在编译时就已经将接口、委托类、代理类等确定下来了,并且在程序运行之前,代理类的.class文件就已经生成。这类代理模式被称为静态代理。

1、确定接口

创建一个名为Person的父类,并设置一个名为sayHello的抽象方法

public interface Person {

    public void sayHello();

}

2、委托类

创建一个名为Student的子类,并实现sayHello的方法

public class Student implements Person{

    private String name;

    public Student() {

    }

    public Student(String name) {
        this.name = name;
    }

    @Override
    public void sayHello() {
        System.out.println(name + "到了");
    }
}

3、代理类

创建一个名为StudentProxy的代理类并继承Person接口,实现sayHello的方法,设置有参构造,参数为被代理的委托类,并在sayHello方法中转发调用消息到对应的委托类中。

public class StudentProxy implements Person{

    private Student student;

    public StudentProxy(Student student) {
        this.student = student;
    }

    @Override
    public void sayHello() {
        System.out.println("班长确认中:");
        student.sayHello();
    }
}

4、执行测试

public class StaticProxy {

    public static void main(String[] args) {
        Person proxy = new StudentProxy(new Student("张三"));
        proxy.sayHello();
    }

}

2、动态代理

代理类在程序运行时创建的代理方式被成为动态代理。

1、JDK动态代理

1、JDK动态代理只能对实现了接口的类生成代理,而不能针对类 ,使用的是 Java反射技术实现,生成类的过程比较高效。
2、JDK代理是不需要第三方库支持,只需要JDK环境就可以进行代理,使用条件:实现InvocationHandler + 使用Proxy.newProxyInstance产生代理对象 + 被代理的对象必须要实现接口

// 实现InvocationHandler接口
public class JdkProxy<T> implements InvocationHandler {

    private T target;

    public JdkProxy(T t) {
        this.target  = t;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("执行代理了哦");
        Object invoke = method.invoke(target, args);
        System.out.println("代理执行完了哦");
        return (T)invoke;
    }
}
public class JdkProxyMain {


    public static void main(String[] args) {
        Person student = new Student("张三");
        // 调用Proxy的newProxyInstance的方法获取到代理类
        Person instance = (Person)Proxy.newProxyInstance(student.getClass().getClassLoader(), student.getClass().getInterfaces(), new JdkProxy<>(student));
        instance.sayHello();
    }

}

2、Cglib动态代理

1、CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 ,使用asm字节码框架实现,相关执行的过程比较高效,生成类的过程可以利用缓存弥补,因为是继承,所以该类或方法最好不要声明成final
2、CGLib必须依赖于CGLib的类库,但是它需要类来实现任何接口代理的是指定的类生成一个子类,覆盖其中的方法,是一种继承但是针对接口编程的环境下推荐使用JDK的代理;

// 实现MethodInterceptor接口
public class CglibProxy implements MethodInterceptor {
    private Object target;

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

    public Person getProxy(Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        //设置父类,因为Cglib是针对指定的类生成一个子类,所以需要指定父类
        enhancer.setSuperclass(target.getClass());
        // 设置回调函数
        enhancer.setCallback(this);
        Object o = enhancer.create();
        return (Person) o;
    }
}
public class CglibProxyMain {

    public static void main(String[] args) {
    	// 实例化CglibProxy对象
        CglibProxy cglibProxy = new CglibProxy();
        // 获取代理对象
        Person person = cglibProxy.getProxy(new Student("张三"));
        person.sayHello();
    }
}

3、注意

在《精通Spring4.x 企业应用开发实战》给出建议:单例使用cglib,多例使用jdk

原因:jdk创建对象性能高于cglib,而生成对象的运行性能却比cglib低

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值