spring源码相关知识

名称解释:

spring核心宗旨:简化开发

DI:依赖注入

IOC:控制反转(将实例化交给spring,用的时候直接在容器中取)

AOP:面向切面 (定义规则,实现解耦)

AOP核心宗旨:解耦

设计模式:

代理模式:

相关角色:执行者(比如:中介、黄牛),被代理人(比如:买房人、买票人)

满足条件:

1.对被代理人来说,事情必须做

2.自己不想做,没时间做,找代理

3.获取到被代理人的个人资料

【个人理解】:

代理模式的实现需要:实现了handler的代理人、被代理人、handler处理器、代理生成器

代理模式通俗来讲就是通过代理生成器生成一个代理类,自己不干的事情,交给代理类来干。

具体实现:主要的点在于代理生成器如何实现??

首先让我自己写应该是这样的:Proxy代理生成器里面有一个newProxyInstance()方法,里面有一个由代理人作为参数的构造方法。

这个方法是这样实现的:

1.根据被代理人的接口、类加载器、实现了handler的代理人,根据接口interfaces.getMethods()拿到所有的方法,循环遍历实现实现这些方法,方法的实现是通过调用handler.invoke()方法,通过反射机制clazz.getMethod拿到invoke的参数,同时将proxy作为参数作为invoke参数,这样以硬编码的方式写成一个代理类

2.将代理类写入磁盘生成为Java文件

3.编译Java文件为class文件

4.加载class文件到jvm

5.返回代理对象

代理生成器:

public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
        throws IllegalArgumentException {
    // validate the parameters
    // ...

    // get the proxy class
    Class<?> proxyClass = getProxyClass(loader, interfaces);

    try {
        // get the proxy class constructor that takes InvocationHandler as an argument
        final Constructor<?> cons = proxyClass.getConstructor(new Class<?>[] { InvocationHandler.class });

        // create a new proxy instance
        return cons.newInstance(new Object[] { h });
    } catch (Exception e) {
        throw new IllegalArgumentException(e.toString());
    }
}

 生成的代理对象:

public class $Proxy0 implements Interface1, Interface2 {
    private InvocationHandler h;

    public $Proxy0(InvocationHandler h) {
        this.h = h;
    }

    @Override
    public void method1() throws Throwable {
        h.invoke(this, Interface1.class.getMethod("method1"), null);
    }

    @Override
    public void method2() throws Throwable {
        h.invoke(this, Interface2.class.getMethod("method2"), null);
    }
}

代理类:

public class MyInvocationHandler implements InvocationHandler {
    private final Object target;

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method call");
        Object result = method.invoke(target, args);
        System.out.println("After method call");
        return result;
    }
}

 使用:

import java.lang.reflect.Proxy;

public class ProxyExample {
    public static void main(String[] args) {
        HelloImpl helloImpl = new HelloImpl();
        HelloInvocationHandler handler = new HelloInvocationHandler(helloImpl);

        Hello proxyInstance = (Hello) Proxy.newProxyInstance(
                helloImpl.getClass().getClassLoader(),
                helloImpl.getClass().getInterfaces(),
                handler
        );

        proxyInstance.sayHello();
    }
}
  • jdk动态代理的实现原理:
  1. 拿到被代理类的引用
  2. jdk代理自动实现一个类(这个类自动实现我们给的代理类的接口)
  3. 把被代理对象的引用拿到了(invoke允许你在代理对象上调用方法时插入自定义的行为。这种机制通常用于在调用实际对象的方法之前或之后执行一些操作,比如日志记录、性能监控、事务管理等)
  4. 重新动态生成一个class
  5. 编译
package com.bytesynch.gatekeeper.sink;

public interface Person {
  void buyTickets();
  String getName();
  String getIDCard();
}

package com.bytesynch.gatekeeper.sink;

import lombok.Data;

@Data
public class XiaoMing implements Person{
  private String name="小明";
  private String IDCard="375666222";

  @Override
  public void buyTickets() {
    System.out.println("需要买一张到南京的火车票");
    System.out.println("时间是5月1号早上发车的");
    System.out.println("想要个软卧下铺");
  }
  public static void main(String[] args) {
    Person instance = (Person)new Huangniu().getInstance(new XiaoMing());
    instance.buyTickets();
  }
}
package com.bytesynch.gatekeeper.sink;

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


public class Huangniu implements InvocationHandler {

  private Person target;//代理对象
  public Object getInstance(Person person){
    this.target=person;
    Class<? extends Person> aClass = person.getClass();
    //根据提供的被代理对象,生成一个代理类,该代理类实现了被代理类的所有接口
    return Proxy.newProxyInstance(aClass.getClassLoader(),aClass.getInterfaces(),this);
  }
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println(this.target.getName()+"买车票之前先做一下思想准备~");
    System.out.println("-----------------------------------");
    method.invoke(this.target,args);
    System.out.println("-----------------------------------");
    System.out.println("我买上票了黄牛还是靠谱的!");
    return null;
  }


}
小明买车票之前先做一下思想准备~
-----------------------------------
需要买一张到南京的火车票
时间是5月1号早上发车的
想要个软卧下铺
-----------------------------------
我买上票了黄牛还是靠谱的!
  • CGLIB 代理

CGLIB(Code Generation Library)是一个强大的字节码生成库,它允许开发者在运行时动态地生成和操作Java类。与Java的标准动态代理机制(java.lang.reflect.Proxy)不同,CGLIB不要求代理类实现接口,而是通过生成目标类的子类来实现代理。因此,CGLIB可以代理没有实现接口的类。下面我们将深入了解CGLIB是如何实现代理的

CGLIB代理的基本工作原理

CGLIB通过继承目标类并重写其方法来实现代理。当方法被调用时,CGLIB代理类会拦截调用,并可以在方法调用前后添加自定义逻辑。

CGLIB的关键组件

  • Enhancer:用于生成代理类的主要类。
  • MethodInterceptor:用于拦截方法调用的接口。

CGLIB代理的实现步骤

  1. 创建Enhancer对象Enhancer 是CGLIB的核心类,用于生成代理类。
  2. 设置父类:代理类将继承目标类。
  3. 设置回调:使用 MethodInterceptor 拦截方法调用。
  4. 生成代理实例:通过 create 方法生成代理实例。

被代理类

public class SampleClass {
    public void test() {
        System.out.println("Hello, world!");
    }
}

代理类

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class SampleMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before method call");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("After method call");
        return result;
    }
}

 使用Enhancer创建代理类

import org.springframework.cglib.proxy.Enhancer;

public class CglibExample {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(SampleClass.class);
        enhancer.setCallback(new SampleMethodInterceptor());

        SampleClass proxy = (SampleClass) enhancer.create();
        proxy.test();
    }
}

 

CGLIB代理生成器如何生成代理类

CGLIB通过以下步骤生成代理类:

  1. 设置类加载器:确定生成代理类时使用的类加载器。
  2. 设置父类:代理类将继承目标类。
  3. 设置回调:定义方法调用时的拦截逻辑。
  4. 生成代理类字节码:使用 ASM 动态生成代理类的字节码。
  5. 定义并加载代理类:通过类加载器加载代理类。
  6. 创建代理实例:通过代理类的构造函数创建代理实例。

大概的生成器Enhancer的代码

 

1. 设置类加载器

Enhancer 使用默认的类加载器,也可以通过 setClassLoader 方法设置自定义的类加载器。

public void setClassLoader(ClassLoader classLoader) {
    this.classLoader = classLoader;
}
2. 设置父类

代理类将继承目标类。通过 setSuperclass 方法设置目标类。

 

public void setSuperclass(Class<?> superclass) {
    this.superclass = superclass;
}
3. 设置回调

定义方法调用时的拦截逻辑。通过 setCallback 方法设置 MethodInterceptor 实现

 

public void setCallback(Callback callback) {
    this.callback = callback;
}
4. 生成代理类字节码

使用 ASM 库生成代理类的字节码。代理类继承目标类,并重写其方法

 

private byte[] generateClass() {
    ClassEmitter ce = new ClassEmitter();
    // 设置类名、父类和接口
    ce.begin_class(Opcodes.V1_8, Opcodes.ACC_PUBLIC, className, superclass.getName(), null, "<generated>");

    // 添加字段
    ce.visitField(Opcodes.ACC_PRIVATE, "CGLIB$CALLBACK_0", Type.getDescriptor(MethodInterceptor.class), null, null);

    // 添加构造函数
    CodeEmitter e = ce.begin_method(Opcodes.ACC_PUBLIC, new Method("<init>", "()V"), null);
    e.load_this();
    e.super_invoke_constructor();
    e.return_value();
    e.end_method();

    // 重写方法
    for (Method method : superclass.getDeclaredMethods()) {
        if (Modifier.isFinal(method.getModifiers())) {
            continue;
        }
        e = ce.begin_method(Opcodes.ACC_PUBLIC, method, null);
        e.load_this();
        e.getfield("CGLIB$CALLBACK_0");
        e.load_this();
        e.load_args();
        e.invoke_interface(MethodInterceptor.class, "intercept");
        e.return_value();
        e.end_method();
    }
    ce.end_class();

    return ce.toByteArray();
}
5. 定义并加载代理类

使用类加载器加载生成的代理类字节码。

 

private Class<?> defineClass(byte[] classBytes) throws Exception {
    ClassLoader loader = classLoader != null ? classLoader : getClass().getClassLoader();
    Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
    defineClass.setAccessible(true);
    return (Class<?>) defineClass.invoke(loader, null, classBytes, 0, classBytes.length);
}

 

6. 创建代理实例

通过代理类的构造函数创建代理实例,并将 MethodInterceptor 赋值给代理实例的回调字段。

public Object create() throws Exception {
    byte[] classBytes = generateClass();
    Class<?> proxyClass = defineClass(classBytes);
    Object proxyInstance = proxyClass.getDeclaredConstructor().newInstance();
    Field callbackField = proxyClass.getDeclaredField("CGLIB$CALLBACK_0");
    callbackField.setAccessible(true);
    callbackField.set(proxyInstance, callback);
    return proxyInstance;
}

 生成的代理类的伪代码

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

public class SampleClass$$EnhancerByCGLIB$$ extends SampleClass {
    // CGLIB 用于存储回调对象的字段
    private MethodInterceptor CGLIB$CALLBACK_0;

    // 默认构造函数
    public SampleClass$$EnhancerByCGLIB$$() {
        super();
    }

    // 重写目标方法 test()
    @Override
    public void test() {
        try {
            // 获取 MethodProxy 对象
            MethodProxy methodProxy = MethodProxy.find(SampleClass.class, "test");

            // 调用 MethodInterceptor 的 intercept 方法
            CGLIB$CALLBACK_0.intercept(this, SampleClass.class.getMethod("test"), null, methodProxy);
        } catch (Throwable t) {
            throw new RuntimeException(t);
        }
    }
    
    // 用于设置回调对象的方法
    public void setCallback(MethodInterceptor callback) {
        this.CGLIB$CALLBACK_0 = callback;
    }
}

 注意:cglib和jdk的动态代理基本思想都是一样的,不同点在于如何生成代理对象上,

jdk是实现一个接口,通过反射的方式Method.invoke()调用被代理类的方法

cglib是代理类生成器,给他生成了一个子类,通过设置回调方法设置定义的MethodInterceptor ,通过它的调用ntercept 方法,其中参数

Object obj, Method method, Object[] args, MethodProxy proxy

第一个参数为生成的子类

第二个参数为Method

第三个参数为method参数

第四个参数为:

MethodProxy methodProxy = MethodProxy.find(SampleClass.class, "test");

public class MethodProxy {
    private final Method originalMethod;
    private final Method proxyMethod;

    private MethodProxy(Method originalMethod, Method proxyMethod) {
        this.originalMethod = originalMethod;
        this.proxyMethod = proxyMethod;
    }

    public static MethodProxy find(Class<?> superClass, String methodName, Class<?>[] parameterTypes) {
        try {
            Method originalMethod = superClass.getDeclaredMethod(methodName, parameterTypes);
            Method proxyMethod = findProxyMethod(superClass, methodName, parameterTypes);
            return new MethodProxy(originalMethod, proxyMethod);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

    public Object invokeSuper(Object obj, Object[] args) throws Throwable {
        return proxyMethod.invoke(obj, args);
    }

    private static Method findProxyMethod(Class<?> superClass, String methodName, Class<?>[] parameterTypes) {
        // 这里实现查找代理方法的逻辑,通常通过 CGLIB 预生成的字节码查找
        // 此处简化为直接调用父类方法
        return superClass.getDeclaredMethod(methodName, parameterTypes);
    }
}
  • AspectJ

TODO待补充

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值