learn and grow up

解析springBean类的注解引发的一系列如AOP|cglib代理等问题三

字数统计: 476阅读时长: 2 min
2020/06/07 Share

写在前面

接上一篇,这篇继续梳理一下自己在查找问题中遇到的疑惑点和解决过程,这篇主要是cglib

疑惑&解答

  1. spring cglib是如何自定义classname的呢?

    之前我们在debug的时候发现spring生产的cglib代理的className都有自己独特的标示,比如:class com.iiap.controller.DeviceController$$EnhancerBySpringCGLIB$$6cf59d5d,这个问题就需要去研究cglib的源码了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    //ClassGenerator cglib生成代理class的顶级接口类
    package net.sf.cglib.core;

    import org.objectweb.asm.ClassVisitor;

    public interface ClassGenerator {
    void generateClass(ClassVisitor v) throws Exception;
    }
    //net.sf.cglib.core.AbstractClassGenerator 基础的实现抽象类,看这个类就可以发现
    protected Class generate(ClassLoaderData data) {
    Class gen;
    Object save = CURRENT.get();
    CURRENT.set(this);
    try {
    ClassLoader classLoader = data.getClassLoader();
    if (classLoader == null) {
    throw new IllegalStateException("ClassLoader is null while trying to define class " +
    getClassName() + ". It seems that the loader has been expired from a weak reference somehow. " +
    "Please file an issue at cglib's issue tracker.");
    }
    //涉及到cacheKey的维护和多线程生成,所以需要加锁
    synchronized (classLoader) {
    //获取className
    String name = generateClassName(data.getUniqueNamePredicate());
    //写入缓存
    data.reserveName(name);
    //设置名称
    this.setClassName(name);
    }
    if (attemptLoad) {
    try {
    gen = classLoader.loadClass(getClassName());
    return gen;
    } catch (ClassNotFoundException e) {
    // ignore
    }
    }
    byte[] b = strategy.generate(this);
    String className = ClassNameReader.getClassName(new ClassReader(b));
    ProtectionDomain protectionDomain = getProtectionDomain();
    synchronized (classLoader) { // just in case
    if (protectionDomain == null) {
    gen = ReflectUtils.defineClass(className, b, classLoader);
    } else {
    gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain);
    }
    }
    return gen;
    } catch (RuntimeException e) {
    throw e;
    } catch (Error e) {
    throw e;
    } catch (Exception e) {
    throw new CodeGenerationException(e);
    } finally {
    CURRENT.set(save);
    }
    }
    //生成class名称
    private String generateClassName(Predicate nameTestPredicate) {
    return namingPolicy.getClassName(namePrefix, source.name, key, nameTestPredicate);
    }

    NamingPolicy就是cglib的命名生成配置类,我们在项目中搜索没发现spring的实现类,再根据类名搜索,就可以发现spring自己写了一套cglib来生成

    NamingPolicy

    看到这里一切都明了了

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    package org.springframework.cglib.core;

    public class SpringNamingPolicy extends DefaultNamingPolicy {
    public static final SpringNamingPolicy INSTANCE = new SpringNamingPolicy();

    public SpringNamingPolicy() {
    }
    //重写父类方法了
    protected String getTag() {
    return "BySpringCGLIB";
    }
    }
CATALOG
  1. 1. 写在前面
  2. 2. 疑惑&解答