写在前面
接上一篇,这篇继续梳理一下自己在查找问题中遇到的疑惑点和解决过程,这篇主要是cglib
疑惑&解答
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来生成
看到这里一切都明了了
1
2
3
4
5
6
7
8
9
10
11
12package org.springframework.cglib.core;
public class SpringNamingPolicy extends DefaultNamingPolicy {
public static final SpringNamingPolicy INSTANCE = new SpringNamingPolicy();
public SpringNamingPolicy() {
}
//重写父类方法了
protected String getTag() {
return "BySpringCGLIB";
}
}