上一節(jié)我們分析了cglib方式實(shí)現(xiàn)aop的基本過(guò)程莉恼,本文將繼續(xù)上一篇的內(nèi)容囚枪,具體講講代理對(duì)象的實(shí)現(xiàn)細(xì)節(jié)发笔。提到代理對(duì)象的產(chǎn)生缸榛,就不得不提Enhancer吝羞,這是cglib中的一個(gè)字節(jié)碼增強(qiáng)器,通過(guò)它我們可以對(duì)目標(biāo)類(lèi)進(jìn)行擴(kuò)展内颗。
本文主要分析以下兩個(gè)問(wèn)題:
1.cglib如何生成代理類(lèi)
2.cglib生成代理的方式中钧排,哪些方法不能被代理
3.cglib的二級(jí)緩存機(jī)制
1.源碼分析
Enhancer中產(chǎn)生代理類(lèi)的入口是幾個(gè)簽名不同的create()方法,但是這幾個(gè)create()方法最終都會(huì)調(diào)用createHelper()方法均澳,因此我們就從createHelper()方法著手:
private Object createHelper() {
// 這里主要是一些參數(shù)校驗(yàn)恨溜,比較簡(jiǎn)單
this.preValidate();
// 根據(jù)代理配置生成緩存的key,作為二級(jí)緩存的key值找前,而一級(jí)緩存的key則是ClassLoader
Object key = KEY_FACTORY.newInstance(this.superclass != null?this.superclass.getName():null, ReflectUtils.getNames(this.interfaces), this.filter == ALL_ZERO?null:new WeakCacheKey(this.filter), this.callbackTypes, this.useFactory, this.interceptDuringConstruction, this.serialVersionUID);
this.currentKey = key;
// 調(diào)用父類(lèi)AbstractClassGenerator的create()方法
Object result = super.create(key);
return result;
}
AbstractClassGenerator是cglib中一個(gè)很重要的類(lèi)糟袁,是字節(jié)碼生成過(guò)程中的一個(gè)核心調(diào)度者,包括緩存躺盛、命名策略系吭、字節(jié)碼生成策略都由它定義,Enhancer就是它的一個(gè)子類(lèi)颗品。
protected Object create(Object key) {
try {
// 獲取類(lèi)加載器
ClassLoader loader = this.getClassLoader();
Map<ClassLoader, AbstractClassGenerator.ClassLoaderData> cache = CACHE;
// 優(yōu)先從緩存加載肯尺,根據(jù)ClassLoader區(qū)分
AbstractClassGenerator.ClassLoaderData data = (AbstractClassGenerator.ClassLoaderData)cache.get(loader);
// 緩存為空,則需要進(jìn)行初始化
if(data == null) {
Class var5 = AbstractClassGenerator.class;
synchronized(AbstractClassGenerator.class) {
cache = CACHE;
data = (AbstractClassGenerator.ClassLoaderData)cache.get(loader);
if(data == null) {
Map<ClassLoader, AbstractClassGenerator.ClassLoaderData> newCache = new WeakHashMap(cache);
data = new AbstractClassGenerator.ClassLoaderData(loader);
// 放入緩存
newCache.put(loader, data);
CACHE = newCache;
}
}
}
// 從緩存加載
this.key = key;
Object obj = data.get(this, this.getUseCache());
return obj instanceof Class?this.firstInstance((Class)obj):this.nextInstance(obj);
}
... 異常處理省略
}
類(lèi)加載器是按照如下順序來(lái)獲取的:加載父類(lèi)或者接口的類(lèi)加載器 -> 自己的類(lèi)加載器 -> 線(xiàn)程上下文類(lèi)加載器躯枢,這個(gè)過(guò)程在上一篇也有提到则吟,這里不再展開(kāi)。
緩存在這個(gè)構(gòu)造函數(shù)中進(jìn)行初始化:
protected static class ClassLoaderData {
public ClassLoaderData(ClassLoader classLoader) {
if(classLoader == null) {
throw new IllegalArgumentException("classLoader == null is not yet supported");
} else {
this.classLoader = new WeakReference(classLoader);
Function<AbstractClassGenerator, Object> load = new Function<AbstractClassGenerator, Object>() {
public Object apply(AbstractClassGenerator gen) {
// 產(chǎn)生字節(jié)碼文件
Class klass = gen.generate(ClassLoaderData.this);
return gen.wrapCachedClass(klass);
}
};
// 生成二級(jí)緩存
this.generatedClasses = new LoadingCache(GET_KEY, load);
}
}
// 判斷是否使用緩存
public Object get(AbstractClassGenerator gen, boolean useCache) {
if(!useCache) {
return gen.generate(this);
} else {
// 從二級(jí)緩存中取出代理對(duì)象
Object cachedValue = this.generatedClasses.get(gen);
return gen.unwrapCachedValue(cachedValue);
}
}
}
protected Class generate(AbstractClassGenerator.ClassLoaderData data) {
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 " + this.getClassName() + ". It seems that the loader has been expired from a weak reference somehow. Please file an issue at cglib's issue tracker.");
} else {
String className;
synchronized(classLoader) {
// 根據(jù)命名策略生成代理類(lèi)類(lèi)名
className = this.generateClassName(data.getUniqueNamePredicate());
data.reserveName(className);
this.setClassName(className);
}
Class gen;
if(this.attemptLoad) {
try {
gen = classLoader.loadClass(this.getClassName());
Class var25 = gen;
return var25;
} catch (ClassNotFoundException var20) {
;
}
}
// 生成二進(jìn)制流锄蹂,默認(rèn)實(shí)現(xiàn)DefaultGeneratorStrategy
byte[] b = this.strategy.generate(this);
className = ClassNameReader.getClassName(new ClassReader(b));
ProtectionDomain protectionDomain = this.getProtectionDomain();
synchronized(classLoader) {
if(protectionDomain == null) {
// 根據(jù)二進(jìn)制流生成字節(jié)碼
gen = ReflectUtils.defineClass(className, b, classLoader);
} else {
gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain);
}
}
Class var8 = gen;
return var8;
}
}
... 省略異常處理
生成代理類(lèi)類(lèi)名的具體邏輯如下:
public String getClassName(String prefix, String source, Object key, Predicate names) {
// prefix一般就是目標(biāo)類(lèi)的全限定名
if(prefix == null) {
prefix = "org.springframework.cglib.empty.Object";
} else if(prefix.startsWith("java")) {
prefix = "$" + prefix;
}
// source就是Enhancer的全限定名
// source.substring(source.lastIndexOf(46) + 1)就是去Enhancer的簡(jiǎn)稱(chēng)
// this.getTag()返回的是"ByCGLIB"
String base = prefix + "$$" + source.substring(source.lastIndexOf(46) + 1) + this.getTag() + "$$" + Integer.toHexString(STRESS_HASH_CODE?0:key.hashCode());
String attempt = base;
for(int var7 = 2; names.evaluate(attempt); attempt = base + "_" + var7++) {
;
}
return attempt;
}
public class DefaultGeneratorStrategy implements GeneratorStrategy {
public byte[] generate(ClassGenerator cg) throws Exception {
DebuggingClassWriter cw = this.getClassVisitor();
this.transform(cg).generateClass(cw);
return this.transform(cw.toByteArray());
}
}
利用Enhancer來(lái)生成代理類(lèi)氓仲,底層也是采用了asm框架,具體實(shí)現(xiàn)如下:
public void generateClass(ClassVisitor v) throws Exception {
Class sc = this.superclass == null?Object.class:this.superclass;
if(TypeUtils.isFinal(sc.getModifiers())) {
throw new IllegalArgumentException("Cannot subclass final class " + sc.getName());
} else {
List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors()));
this.filterConstructors(sc, constructors);
List actualMethods = new ArrayList();
List interfaceMethods = new ArrayList();
final Set forcePublic = new HashSet();
// 采用遞歸的方式,找到目標(biāo)類(lèi)的父類(lèi)敬扛、接口的所有方法晰洒,并過(guò)濾掉滿(mǎn)足條件的方法,具體條件后文有詳細(xì)說(shuō)明
getMethods(sc, this.interfaces, actualMethods, interfaceMethods, forcePublic);
// 對(duì)方法的修飾符作了變化啥箭,保存到methods中谍珊,轉(zhuǎn)換之前的方法保存在actualMethods中
List methods = CollectionUtils.transform(actualMethods, new Transformer() {
public Object transform(Object value) {
Method method = (Method)value;
// 在Modifier類(lèi)中,1024急侥、256砌滞、32、16分別表示abstract坏怪、native贝润、synchronized、final修飾符铝宵,因此這句話(huà)的意思是將abstract打掘、native、synchronized修飾符全部去掉鹏秋,然后加上final修飾符
int modifiers = 16 | method.getModifiers() & -1025 & -257 & -33;
// 同理尊蚁,這里是把protected修飾符換成public
if(forcePublic.contains(MethodWrapper.create(method))) {
modifiers = modifiers & -5 | 1;
}
return ReflectUtils.getMethodInfo(method, modifiers);
}
});
// 這里有一段是根據(jù)asm框架產(chǎn)生字節(jié)碼了,還沒(méi)看懂拼岳,先跳過(guò)o(╯□╰)o
......
if(this.currentData == null) {
// 上一篇講過(guò)枝誊,CallbackFilter作為回調(diào)過(guò)濾器况芒,其核心方法為accept()惜纸,返回值為int類(lèi)型,代表了回調(diào)入口在callbacks數(shù)組中的位置绝骚,這里就是完成了CallbackFilter的處理耐版,確定每個(gè)方法分別有哪個(gè)過(guò)濾器來(lái)處理
this.emitMethods(e, methods, actualMethods);
this.emitConstructors(e, constructorInfo);
} else {
this.emitDefaultConstructor(e);
}
......
e.end_class();
}
}
getMethods方法具體實(shí)現(xiàn)邏輯:
private static void getMethods(Class superclass, Class[] interfaces, List methods, List interfaceMethods, Set forcePublic) {
// 遞歸添加父類(lèi)的所有方法
ReflectUtils.addAllMethods(superclass, methods);
List target = interfaceMethods != null?interfaceMethods:methods;
// 遞歸添加接口的所有方法
if(interfaces != null) {
for(int i = 0; i < interfaces.length; ++i) {
if(interfaces[i] != Factory.class) {
ReflectUtils.addAllMethods(interfaces[i], target);
}
}
}
if(interfaceMethods != null) {
if(forcePublic != null) {
forcePublic.addAll(MethodWrapper.createSet(interfaceMethods));
}
methods.addAll(interfaceMethods);
}
// 過(guò)濾掉靜態(tài)方法,在Modifier類(lèi)中压汪,靜態(tài)方法的標(biāo)識(shí)就是0x00000008
CollectionUtils.filter(methods, new RejectModifierPredicate(8));
// 過(guò)濾掉不可見(jiàn)的方法(包括兩類(lèi):私有方法粪牲、默認(rèn)修飾符且與目標(biāo)類(lèi)不在同一個(gè)包中的方法)
CollectionUtils.filter(methods, new VisibilityPredicate(superclass, true));
// 過(guò)濾掉重復(fù)的方法(方法名、入?yún)⒑头祷仡?lèi)型都相同的方法)
CollectionUtils.filter(methods, new DuplicatesPredicate());
// 過(guò)濾掉final方法止剖,在Modifier類(lèi)中腺阳,靜態(tài)方法的標(biāo)識(shí)就是0x00000010
CollectionUtils.filter(methods, new RejectModifierPredicate(16));
}
emitMethods方法具體實(shí)現(xiàn)邏輯:
private void emitMethods(ClassEmitter ce, List methods, List actualMethods) {
CallbackGenerator[] generators = CallbackInfo.getGenerators(this.callbackTypes);
Map groups = new HashMap();
final Map indexes = new HashMap();
final Map originalModifiers = new HashMap();
final Map positions = CollectionUtils.getIndexMap(methods);
Map declToBridge = new HashMap();
Iterator it1 = methods.iterator();
Iterator it2 = actualMethods != null?actualMethods.iterator():null;
while(it1.hasNext()) {
MethodInfo method = (MethodInfo)it1.next();
Method actualMethod = it2 != null?(Method)it2.next():null;
// 選擇具體的回調(diào)過(guò)濾器
int index = this.filter.accept(actualMethod);
if(index >= this.callbackTypes.length) {
throw new IllegalArgumentException("Callback filter returned an index that is too large: " + index);
}
// 把方法和其對(duì)應(yīng)的修飾符的映射關(guān)系保存起來(lái)
originalModifiers.put(method, new Integer(actualMethod != null?actualMethod.getModifiers():method.getModifiers()));
// 把方法和其對(duì)應(yīng)的回調(diào)過(guò)濾器下表的映射關(guān)系保存起來(lái)
indexes.put(method, new Integer(index));
List group = (List)groups.get(generators[index]);
if(group == null) {
groups.put(generators[index], group = new ArrayList(methods.size()));
}
((List)group).add(method);
// 建立類(lèi)和橋接方法之間的映射關(guān)系
// 橋接方法:jdk1.5引入了泛型,并且在編譯期會(huì)進(jìn)行類(lèi)型擦除穿香,因此字節(jié)碼文件中集合元素類(lèi)型都是Object亭引,同時(shí)由于對(duì)類(lèi)型的校驗(yàn)也提前到了編譯期,因此編譯期會(huì)生成一個(gè)橋接方法皮获,將Object類(lèi)型轉(zhuǎn)換為實(shí)際類(lèi)型焙蚓。
if(TypeUtils.isBridge(actualMethod.getModifiers())) {
Set bridges = (Set)declToBridge.get(actualMethod.getDeclaringClass());
if(bridges == null) {
bridges = new HashSet();
declToBridge.put(actualMethod.getDeclaringClass(), bridges);
}
((Set)bridges).add(method.getSignature());
}
}
// 又是一堆根據(jù)asm生成字節(jié)碼的邏輯,暫時(shí)略過(guò)o(╯□╰)o
......
}
2.測(cè)試
好了,源碼總是虛無(wú)縹緲的购公,我們接下來(lái)舉一個(gè)實(shí)際的栗子來(lái)看一看萌京。
目標(biāo)類(lèi):
public class Target {
public void exeTarget() {
System.out.println("execute target.");
}
}
增強(qiáng)類(lèi):
public class BeforeAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("before advice.");
}
}
配置文件:
<bean id="adviceSeq" class="org.springframework.aop.framework.ProxyFactoryBean"
p:target-ref="target"
p:proxyTargetClass="true"
p:frozen="true"
p:interceptorNames="beforeAdvice"/>
測(cè)試類(lèi):
public class AdviceSeqTest {
public static void main(String[] args) {
// 將產(chǎn)生的代理類(lèi)文件寫(xiě)入磁盤(pán)
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, ".//");
String configPath = "advice/seq/beans.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(configPath);
Target target = (Target) context.getBean("adviceSeq");
target.exeTarget();
}
}
運(yùn)行測(cè)試類(lèi)后,得到的代理類(lèi)class文件名為T(mén)arget$$EnhancerBySpringCGLIB$$8b53f595.class宏浩,跟我們前面的分析一致知残,目標(biāo)方法的代理方法為如下,靜態(tài)方法exeStaticTarget()绘闷、私有privateMethod()和final方法finalMethod()在生成的代理類(lèi)中都不存在:
// 跟之前分析的一樣橡庞,方法加上了final修飾符
public final void exeTarget() {
try {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if(this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
// 如果回調(diào)函數(shù)不為空,執(zhí)行攔截印蔗,否則直接調(diào)用目標(biāo)方法
if(var10000 != null) {
var10000.intercept(this, CGLIB$exeTarget$6$Method, CGLIB$emptyArgs, CGLIB$exeTarget$6$Proxy);
} else {
super.exeTarget();
}
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
}