Java基础知识 - 静态代理/JDK动态代理/Cglib动态代理

createh54个月前 (01-07)技术教程47

1)代理的作用是为指定类构建代理类;

1、指定类可能不能够直接被访问,所以在外层包一层代理类,让执行代理类方法;

2、也有可能想在执行指定类的方法前后,做一些自己的事情,也可以使用代理类;

2)使用哪种代理模式;

1、可以直接使用静态代理类;

2、在对接口使用代理时,如果接口中方法太多,就可以使用 JDK 动态代理,而不需要使用静态代理去实现接口的每个方法;

3、在对类做代理时,可以使用静态代理,也可以使用动态代理,但是 JDK 动态代理只支持接口级别,那可以使用 Cglib 动态代理;


1、静态代理

1.1、第一种场景-给类做代理


1.2、第二种场景-给接口做代理


2、JDK动态代理

1)JDK代理是动态代理,只能针对接口做代理

2)要用到 java.lang.reflect.Proxy 代理类;

3)利用 JDK 动态代理可以在运行时创建实现了一组给定接口的代理类;

4)如果接口中方法众多,而你也只是想针对某几个方法做代理处理,那么可以使用动态代理;

5)运行时创建的动态代理类会实现指定接口中的所有方法,并实现 Object 类中的方法;

不过动态代理类不能在运行时加一些额外的自己的代码,但是可以在调用处理器中的 invoke 方法中在执行反射 method.invoke() 时在前后加一些自己的额外代码

6)java.lang.reflect.Proxy 代理类通过 newProxyInstance 方法创建代理类,该方法有三个参数;

1、ClassLoader loader,类加载器;

2、Class<?>[] interfaces,接口数组,数组中的元素是需要代理类实现的接口;

3、InvocationHandler h,调用处理器;

7)代理类是在程序运行过程中动态创建的,一旦被创建就变成常规类,与虚拟机中其他类没有什么区别;

8)所有的代理类都扩展 Proxy 类,一个代理类中只有一个调用处理器实例字段;

9)代理类都实现了指定接口中的所有方法;

10)代理类在执行方法时,其实是通过其内部的调用处理器执行 invoke 方法,而我们实现的 invoke 方法实际是反射执行被代理类的方法;


2.1、实践一

1)JDK 动态代理要求调用处理器中的 target 对象必须是一个实现接口的类,该接口需是 newProxyInstance 方法中指定的接口;


2.2、实践二


3、Cglib动态代理

1)JDK 动态代理要求调用处理器中的 target 对象必须是一个实现接口的类,对于没有实现接口的类可以使用 Cglib 做动态代理;

2)Cglib,Code Generation Library;

3)Cglib 是通过创建 target 对象的子类对象来实现对 target 对象的代理,即该子类对象就是代理类对象;

1、因为是通过子类的方式实现动态代理,所以 target 对象不能是 final 修饰的类;

2、target 类中的方法不能是 final 和 static 的;


3.1、实践

package com.mfz.proxy;

public class EClass {

    public void printData() {
        System.out.println("EClass printData");
    }
    
    public String sayHello(String name) {
        System.out.println("EClass sayHello " + name);
        return "hello " + name;
    }
    
}
package com.mfz.proxy;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor {

    private Object target;
    public CglibProxy(Object t) {
        this.target = t;
    }
    
    public Object getProxyInstance() {
        //工具类
        Enhancer en = new Enhancer();
        //设置父类
        en.setSuperclass(target.getClass());
        //设置回调函数
        en.setCallback(this);
        //创建子类代理对象
        return en.create();
    }
    
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("CglibProxy Start");
        Object result = method.invoke(target, args);
        System.out.println("CglibProxy End");
        return result;
    }

}

相关文章

Java类中静态方法和静态变量,静态代码块,构造方法执行顺序

一,Java类执行顺序子类:ATest父类:AParentTest直接调用静态方法第一种:当直接调用(没有new对象)静态方法时候:父类静态变量(按照顺序)执行----->子类静态变量(按照顺序...

为何要在Java中使用静态类?

在Java中,static关键字可以被用于变量,类,代码块和方法。当我们使用static关键字去修饰它们之中的任何一个时,意味着这个指定的成员从属与这个类型本身。换言之, 一个静态成员被创建完成后可以...

详解Java中的静态代理和动态代理

代理是一种设计模式在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。目的:为其他...

教你如何在Java中更好的定义常量

关于Java中常量的话题似乎有很多困惑。有些人使用整数或字符串来定义常量,而另一些人则使用枚举。我还遇到了在它们自己的接口中定义的常量——在接口中,使用常量的类必须实现接口。这种策略通常被称为接口常量...

Java基础 —— 泛型

Java基础 —— 泛型泛型?泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。理解?为了可以进一步理解泛型,我们先来看一个问题需求:?编写一个程序,在ArrayList中添...

9分钟带你搞懂代理模式、静态代理、JDK+CGLIB动态代理

目录:1. 代理模式2. 静态代理3. 动态代理3.1. JDK 动态代理机制3.2. CGLIB 动态代理机制3.3. JDK 动态代理和 CGLIB 动态代理对比4. 静态代理和动态代理的对比5....