在AOP3里我提到了proxy-target-class属性,这个属性的值决定是继承接口的还是基于类的代理被创建。
(1)如果为true,那么使用cglib的动态代理。
(2)如果为true为false或这不设置,那么aop根据类是否继承接口决定用哪一种代理方式。
那么cglib的代理方式是怎么实现的呢,一起来探究一下:
jdk的动态代理是用反射实现的,这里就不展开叙述了,先来写一段cglib的代理实现代码:
//先写个被拦截的service
public class TestCglibService {
public void test() {
System.out.println("开始执行TestCglibService...");
}
}
//定义一个CglibProxy动态代理类,并且让它继承MethodInterceptor
public class CglibProxy implements MethodInterceptor{
//被代理的目标对象
private Object targetObject ;
public Object createProxyInstance(Object targetObject) {
this.targetObject = targetObject;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetObject.getClass());// 设置代理目标
enhancer.setCallback(this);// 设置回调
return enhancer.create();
}
@Override
public Object intercept(Object object, Method method, Object[] args,
MethodProxy methodproxy) throws Throwable {
Object result = null;
try {
// before方法
System.out.println("before ...");
result = methodproxy.invoke( targetObject , args);//执行目标对象的方法
// after方法
System.out.println("after ...");
} catch (Exception e) {
System.out.println("异常处理 ...");
} finally {
System.out.println("调用结束 ...");
}
return result;
}
}
public class test {
public static void main(String[] args) {
//1-实例化需要被代理的类
TestCglibService testCglibService = new TestCglibService();
//2-实例化代理工厂
CglibProxy cglibProxy = new CglibProxy();
//3-动态生成一个代理类,并从Object强制转型成父类型
TestCglibService testService =(TestCglibService)cglibProxy.createProcy(testCglibService);
//4-执行动态代理类的方法
testService.test();
}
}
Enhancer类是Cglib中的一个字节码增强器,在调用setSuperclass和setCallback设置代理目标和回调类之后,进入create方法中中:
public Object create() {
this.classOnly = false;
this.argumentTypes = null;
return this.createHelper();
}
private Object createHelper() {
this.preValidate();
//根据当前的配置形成一个key,这样可以利用缓存来存数据。
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;
Object result = super.create(key);
return result;
}
protected Object create(Object key) {
try {
//获取当前的类加载器
ClassLoader loader = this.getClassLoader();
//尝试从缓存中获取类加载数据
Map<ClassLoader, AbstractClassGenerator.ClassLoaderData> cache = CACHE;
AbstractClassGenerator.ClassLoaderData data = (AbstractClassGenerator.ClassLoaderData)cache.get(loader);
if (data == null) {
Class var5 = AbstractClassGenerator.class;
synchronized(AbstractClassGenerator.class) {
cache = CACHE;
data = (AbstractClassGenerator.ClassLoaderData)cache.get(loader);
//再次尝试获取,再次获取不到会根据当前类加载器loader生成ClassLoaderData对象,放到缓存。
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);
} catch (RuntimeException var9) {
throw var9;
} catch (Error var10) {
throw var10;
} catch (Exception var11) {
throw new CodeGenerationException(var11);
}
}
public ClassLoaderData(ClassLoader classLoader) {
if (classLoader == null) {
throw new IllegalArgumentException("classLoader == null is not yet supported");
} else {
this.classLoader = new WeakReference(classLoader);
//定义了一个方法对象,apply方法中定义了具体逻辑。
Function<AbstractClassGenerator, Object> load = new Function<AbstractClassGenerator, Object>() {
public Object apply(AbstractClassGenerator gen) {
// 产生字节码文件
Class klass = gen.generate(ClassLoaderData.this);
return gen.wrapCachedClass(klass);
}
};
this.generatedClasses = new LoadingCache(GET_KEY, load);
}
}
protected Class generate(AbstractClassGenerator.ClassLoaderData data) {
Object save = CURRENT.get();
CURRENT.set(this);
Class var8;
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.");
}
String className;
synchronized(classLoader) {
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) {
;
}
}
byte[] b = this.strategy.generate(this);
className = ClassNameReader.getClassName(new ClassReader(b));
ProtectionDomain protectionDomain = this.getProtectionDomain();
synchronized(classLoader) {
if (protectionDomain == null) {
gen = ReflectUtils.defineClass(className, b, classLoader);
} else {
gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain);
}
}
var8 = gen;
} catch (RuntimeException var21) {
throw var21;
} catch (Error var22) {
throw var22;
} catch (Exception var23) {
throw new CodeGenerationException(var23);
} finally {
CURRENT.set(save);
}
return var8;
}
DefaultNamingPolicy的getClassName方法:
public String getClassName(String prefix, String source, Object key, Predicate names) {
if (prefix == null) {
prefix = "org.springframework.cglib.empty.Object";
} else if (prefix.startsWith("java")) {
prefix = "$" + prefix;
}
//source截取得到的是..+ "$$"+EnhancerByCGLIB+ Integer.toHexString..
//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;
}
最后在defineClass中实现对类的加载:
public static Class defineClass(String className, byte[] b, ClassLoader loader, ProtectionDomain protectionDomain) throws Exception {
Object[] args;
Class c;
//如果DEFINE_CLASS不为null,利用此Method的反射方法。
if (DEFINE_CLASS != null) {
args = new Object[]{className, b, new Integer(0), new Integer(b.length), protectionDomain};
c = (Class)DEFINE_CLASS.invoke(loader, args);
} else {
if (DEFINE_CLASS_UNSAFE == null) {
throw new CodeGenerationException(THROWABLE);
}
args = new Object[]{className, b, new Integer(0), new Integer(b.length), loader, protectionDomain};
c = (Class)DEFINE_CLASS_UNSAFE.invoke(UNSAFE, args);
}
//把该类加载到jvm中。
Class.forName(className, true, loader);
return c;
}
//底层用asm框架对类做处理
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();
getMethods(sc, this.interfaces, actualMethods, interfaceMethods, forcePublic);
//Modifier类中,1024、256、32、16分别表示abstract、native、synchronized、final修饰符,在这会把上述几种类型统一加上final修饰符做处理
List methods = CollectionUtils.transform(actualMethods, new Transformer() {
public Object transform(Object value) {
Method method = (Method)value;
int modifiers = 16 | method.getModifiers() & -1025 & -257 & -33;
if (forcePublic.contains(MethodWrapper.create(method))) {
modifiers = modifiers & -5 | 1;
}
return ReflectUtils.getMethodInfo(method, modifiers);
}
});
ClassEmitter e = new ClassEmitter(v);
if (this.currentData == null) {
e.begin_class(46, 1, this.getClassName(), Type.getType(sc), this.useFactory ? TypeUtils.add(TypeUtils.getTypes(this.interfaces), FACTORY) : TypeUtils.getTypes(this.interfaces), "<generated>");
} else {
e.begin_class(46, 1, this.getClassName(), (Type)null, new Type[]{FACTORY}, "<generated>");
}
List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());
e.declare_field(2, "CGLIB$BOUND", Type.BOOLEAN_TYPE, (Object)null);
e.declare_field(9, "CGLIB$FACTORY_DATA", OBJECT_TYPE, (Object)null);
if (!this.interceptDuringConstruction) {
e.declare_field(2, "CGLIB$CONSTRUCTED", Type.BOOLEAN_TYPE, (Object)null);
}
e.declare_field(26, "CGLIB$THREAD_CALLBACKS", THREAD_LOCAL, (Object)null);
e.declare_field(26, "CGLIB$STATIC_CALLBACKS", CALLBACK_ARRAY, (Object)null);
if (this.serialVersionUID != null) {
e.declare_field(26, "serialVersionUID", Type.LONG_TYPE, this.serialVersionUID);
}
for(int i = 0; i < this.callbackTypes.length; ++i) {
e.declare_field(2, getCallbackField(i), this.callbackTypes[i], (Object)null);
}
e.declare_field(10, "CGLIB$CALLBACK_FILTER", OBJECT_TYPE, (Object)null);
if (this.currentData == null) {
this.emitMethods(e, methods, actualMethods);
this.emitConstructors(e, constructorInfo);
} else {
this.emitDefaultConstructor(e);
}
this.emitSetThreadCallbacks(e);
this.emitSetStaticCallbacks(e);
this.emitBindCallbacks(e);
if (this.useFactory || this.currentData != null) {
int[] keys = this.getCallbackKeys();
this.emitNewInstanceCallbacks(e);
this.emitNewInstanceCallback(e);
this.emitNewInstanceMultiarg(e, constructorInfo);
this.emitGetCallback(e, keys);
this.emitSetCallback(e, keys);
this.emitGetCallbacks(e);
this.emitSetCallbacks(e);
}
e.end_class();
}
}
到这一步,生成类文件并返回。接下来调用方法时,会回调定义好的intercept方法,到MethodProxy中的invoke方法:
public Object invoke(Object obj, Object[] args) throws Throwable {
try {
this.init();
MethodProxy.FastClassInfo fci = this.fastClassInfo;
return fci.f1.invoke(fci.i1, obj, args);
} catch (InvocationTargetException var4) {
throw var4.getTargetException();
} catch (IllegalArgumentException var5) {
if (this.fastClassInfo.i1 < 0) {
throw new IllegalArgumentException("Protected method: " + this.sig1);
} else {
throw var5;
}
}
}
private void init() {
if (this.fastClassInfo == null) {
Object var1 = this.initLock;
synchronized(this.initLock) {
if (this.fastClassInfo == null) {
MethodProxy.CreateInfo ci = this.createInfo;
MethodProxy.FastClassInfo fci = new MethodProxy.FastClassInfo();
fci.f1 = helper(ci, ci.c1);
fci.f2 = helper(ci, ci.c2);
fci.i1 = fci.f1.getIndex(this.sig1);
fci.i2 = fci.f2.getIndex(this.sig2);
this.fastClassInfo = fci;
this.createInfo = null;
}
}
}
}
在init方法中,做了方法索引绑定。每个方法都有对应的index,方法调用时会首先获得具体索引。所以cglib之所以会高效,就是方法调用的处理并没有使用反射,反射调用需要经过本地方法,而Cglib采用了通过给每个代理类方法分配索引,通过index来直接查找具体方法。
总结:
cglib用开源asm框架,通过Enhancer类生成一个代理类,并让此代理类继承目标类,成为其子类。然后在代理类中采用方法拦截的技术,拦截所有父类方法的调用,横切加入我们自定义的处理逻辑。代理类将目标类作为自己的父类,并为其中的每个非final委托方法,创建两个方法:
(1)一个是与目标方法签名相同的方法,它在方法中通过super调用父类的方法。
(2)另一个是代理类独有的方法,称之为 Callback回调方法,也就是我们在 intercept() 方法中定义好的逻辑。它会判断这个方法是否绑定了拦截器(实现了 MethodInterceptor 接口的对象),如果存在,则将调用 intercept() 方法,对目标方法进行代理。