今天我们来分析AOP
技术的核心: 代理。
代理的作用就是在不改变目标方法的情况下,为目标方法添加新功能。
一. 介绍
1.1 静态代理
public interface TI {
void play();
}
public class T implements TI {
public void play() {
System.out.println("I am T");
}
}
public class TProxy implements TI {
private TI t;
public TProxy(TI t) {
this.t = t;
}
@Override
public void play() {
long start = System.currentTimeMillis();
t.play();
System.out.println("一共花费了:"+ (System.currentTimeMillis() - start) +"毫秒");
}
}
public class Test {
public static void main(String[] args) {
TI target = new T();
TI proxy = new TProxy(target);
proxy.play();
}
}
运行结果:
I am T
一共花费了:0毫秒
这是一个静态代理的标准写法,分为三个部分:
-
target
: 类型是T
,目标对象实例。 -
proxy
: 类型是TProxy
,代理对象实例。 -
TI
: 目标对象实例和代理对象实例共同的父接口。
1.2 动态代理
public static void main(String[] args) {
TI target = new T();
TI proxy = (TI) Proxy.newProxyInstance(TI.class.getClassLoader(),
new Class[]{TI.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(String.format("proxy[%s] method[%s] args[%s]",
proxy.getClass().getName(), method.getName(), Arrays.toString(args)));
long start = System.currentTimeMillis();
method.invoke(target, args);
System.out.println("一共花费了:"+ (System.currentTimeMillis() - start) +"毫秒");
return null;
}
});
proxy.play();
}
运行结果:
proxy[com.sun.proxy.$Proxy0] method[play] args[null]
I am T
一共花费了:0毫秒
与静态代理相比较,唯一的区别就是:
- 静态代理写
TProxy
代理类,然后创建代理类实例proxy
,并将目标类实例放入代理类实例proxy
中,最后调用代理类实例proxy
对应方法。
*动态代理不用写代理类,而且通过Proxy
创建代理类实例proxy
,需要传递一个InvocationHandler
实例对象,然后通过反射的方式调用目标类实例对应方法。
1.3 cglib
代理
public static void main(String[] args) {
TI target = new T();
Enhancer e = new Enhancer();
e.setSuperclass(T.class);
e.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
long start = System.currentTimeMillis();
methodProxy.invoke(target, objects);
System.out.println("一共花费了:"+ (System.currentTimeMillis() - start) +"毫秒");
return null;
}
});
T proxy = (T) e.create();
proxy.play();
}
运行结果
I am T
一共花费了:17毫秒
与静态代理相比较,看起来比较复杂,它需要通过Enhancer
创建代理实例proxy
,然后调用代理方法。但是这里比较神奇的是代理类居然是 T
的子类,这些我们下面分析。
二. 动态代理原理
2.1 newProxyInstance
方法
首先分析一下 Proxy.newProxyInstance(...)
方法:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
这个方法流程主要分成三步:
- 检查一下传入的参数。
- 通过
getProxyClass0(loader, intfs)
方法查找或者生成代理类的Class
。 - 获取代理类的构造方法,创建代理类实例。
2.2 getProxyClass0
方法
那么重点就是这个 getProxyClass0(loader, intfs)
方法了。
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
return proxyClassCache.get(loader, interfaces);
}
getProxyClass0(loader, intfs)
方法主要就是从 proxyClassCache
缓存中查找或者生成代理类的 Class
。
WeakCache<K, P, V>
有三个泛型变量:
-
K
: 缓存的key
的类型。 -
P
: 缓存参数类型。 -
V
: 缓存的value
的类型。
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
因此 proxyClassCache
缓存实例的key
是类加载器ClassLoader
,参数是类数组Class<?>[]
,缓存的值是Class
实例。
KeyFactory
是用Key
值和参数值来创建缓存中唯一的键的值。ProxyClassFactory
是用来生成缓存值的实例。
2.3 KeyFactory
类
private static final class KeyFactory
implements BiFunction<ClassLoader, Class<?>[], Object>
{
@Override
public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
switch (interfaces.length) {
case 1: return new Key1(interfaces[0]); // the most frequent
case 2: return new Key2(interfaces[0], interfaces[1]);
case 0: return key0;
default: return new KeyX(interfaces);
}
}
}
根据代理的接口数组interfaces
生成不同的缓存中key
值。
private static final class Key1 extends WeakReference<Class<?>> {
private final int hash;
Key1(Class<?> intf) {
super(intf);
this.hash = intf.hashCode();
}
@Override
public int hashCode() {
return hash;
}
@Override
public boolean equals(Object obj) {
Class<?> intf;
return this == obj ||
obj != null &&
obj.getClass() == Key1.class &&
(intf = get()) != null &&
intf == ((Key1) obj).get();
}
}
2.4 ProxyClassFactory
类
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
// prefix for all proxy class names
private static final String proxyClassNamePrefix = "$Proxy";
// next number to use for generation of unique proxy class names
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces)
{ .... }
}
这个就是代理类的生成器,有两个静态变量:
-
proxyClassNamePrefix
: 所有代理类名的前缀。 -
nextUniqueNumber
: 下一个用于生成唯一代理类名的数字。
重点分析 apply
方法
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
/*
* Verify that the class loader resolves the name of this
* interface to the same Class object.
*/
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
/*
* Verify that the Class object actually represents an
* interface.
*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
* Verify that this interface is not a duplicate.
*/
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
......
}
首先需要检查参数,接口数组 interfaces
的类加载器是不是就是 loader
,接口数组 interfaces
是不是都是接口类型,接口数组 interfaces
有没有重复的接口。
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
......
String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
/*
* Record the package of a non-public proxy interface so that the
* proxy class will be defined in the same package. Verify that
* all non-public proxy interfaces are in the same package.
*/
for (Class<?> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
// if no non-public proxy interfaces, use com.sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
......
}
验证接口数组 interfaces
类的访问权限,以及生成代理类名字 proxyName
。
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
/*
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
/*
* A ClassFormatError here means that (barring bugs in the
* proxy class generation code) there was some other
* invalid aspect of the arguments supplied to the proxy
* class creation (such as virtual machine limitations
* exceeded).
*/
throw new IllegalArgumentException(e.toString());
}
......
}
通过 ProxyGenerator.generateProxyClass(...)
方法生成代理类,并通过类加载器 loader
加载它。
2.5 ProxyGenerator
public static byte[] generateProxyClass(final String name,
Class<?>[] interfaces,
int accessFlags)
{
ProxyGenerator gen = new ProxyGenerator(name, interfaces, accessFlags);
final byte[] classFile = gen.generateClassFile();
if (saveGeneratedFiles) {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
try {
int i = name.lastIndexOf('.');
Path path;
if (i > 0) {
Path dir = Paths.get(name.substring(0, i).replace('.', File.separatorChar));
Files.createDirectories(dir);
path = dir.resolve(name.substring(i+1, name.length()) + ".class");
} else {
path = Paths.get(name + ".class");
}
Files.write(path, classFile);
return null;
} catch (IOException e) {
throw new InternalError(
"I/O exception saving generated file: " + e);
}
}
});
}
return classFile;
}
这个方法流程比较简单:
- 创建
ProxyGenerator
实例。 - 通过
gen.generateClassFile()
方法生成代理类。 - 如果
saveGeneratedFiles
是true
,那么就将代理类写到本地文件中。
饶了一大圈,终于找到了生成代理类的实现方法了,下面我们就分析一下gen.generateClassFile()
方法。
private byte[] generateClassFile() {
addProxyMethod(hashCodeMethod, Object.class);
addProxyMethod(equalsMethod, Object.class);
addProxyMethod(toStringMethod, Object.class);
......
}
将 Object
类的 hash
,equals
和toString
方法添加到代理类的方法集合proxyMethods
。
private byte[] generateClassFile() {
......
for (Class<?> intf : interfaces) {
for (Method m : intf.getMethods()) {
addProxyMethod(m, intf);
}
}
......
}
遍历接口数组interfaces
,将接口中的方法都添加到代理类的方法集合proxyMethods
。
private byte[] generateClassFile() {
......
for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
checkReturnTypes(sigmethods);
}
......
}
检查一下方法集合 proxyMethods
中具有相同签名的方法列表返回值类型。
private byte[] generateClassFile() {
......
try {
methods.add(generateConstructor());
for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
for (ProxyMethod pm : sigmethods) {
// add static field for method's Method object
fields.add(new FieldInfo(pm.methodFieldName,
"Ljava/lang/reflect/Method;",
ACC_PRIVATE | ACC_STATIC));
// generate code for proxy method and add it
methods.add(pm.generateMethod());
}
}
methods.add(generateStaticInitializer());
} catch (IOException e) {
throw new InternalError("unexpected I/O Exception", e);
}
if (methods.size() > 65535) {
throw new IllegalArgumentException("method limit exceeded");
}
if (fields.size() > 65535) {
throw new IllegalArgumentException("field limit exceeded");
}
......
}
生成代理类中所有字段fields
和方法methods
。
代理类中每一个方法,都会有一个对应的
java/lang/reflect/Method
类型的字段。
private byte[] generateClassFile() {
......
cp.getClass(dotToSlash(className));
cp.getClass(superclassName);
for (Class<?> intf: interfaces) {
cp.getClass(dotToSlash(intf.getName()));
}
/*
* Disallow new constant pool additions beyond this point, since
* we are about to write the final constant pool table.
*/
cp.setReadOnly();
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(bout);
try {
/*
* Write all the items of the "ClassFile" structure.
* See JVMS section 4.1.
*/
// u4 magic;
dout.writeInt(0xCAFEBABE);
// u2 minor_version;
dout.writeShort(CLASSFILE_MINOR_VERSION);
// u2 major_version;
dout.writeShort(CLASSFILE_MAJOR_VERSION);
cp.write(dout); // (write constant pool)
......
}
return bout.toByteArray();
}
开始生成代理类的字节码数据。
2.6 示例
以我们之前例子代码
public static void main(String[] args) {
TI target = new T();
TI proxy = (TI) Proxy.newProxyInstance(TI.class.getClassLoader(),
new Class[]{TI.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(String.format("proxy[%s] method[%s] args[%s]",
proxy.getClass().getName(), method.getName(), Arrays.toString(args)));
long start = System.currentTimeMillis();
method.invoke(target, args);
System.out.println("一共花费了:"+ (System.currentTimeMillis() - start) +"毫秒");
return null;
}
});
proxy.play();
}
生成的代理类如下:
package com.sun.proxy;
import com.zhang.bytecode.proxy.TI;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements TI {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void play() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.zhang.bytecode.proxy.TI").getMethod("play");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
我们观察到如下特点:
- 代理类继承自
Proxy
类,实现了我们传递的代理接口TI
,类名就叫$Proxy0
。 - 代理类有四个静态字段,分别对应代理类的四个方法
equals
,hashCode
,toString
和play
。这些静态字段,通过静态代码块中赋值,类型都是
Method
,用于反射调用目标方法。 - 代理类有四个方法,它们都是调用
InvocationHandler
实例的invoke
方法,传递代理类实例this
,对应的代理方法Method
和方法参数agrs
。
2.7 小结
动态代理实现原理我们已经清楚了,那么它的缺点也是显而易见的,主要是两点:
- 只能代理接口,这个是由动态代理生成代理类的原理决定的,只能生成实现接口的代理类。
- 通过反射调用目标方法,必定会影响效率。
2.8 注解的实现
2.8.1 注解是类还是接口
大家有没有想过,我们使用注解是类还是接口呢。
我们简单写一个注解类:
public @interface TA {
int age() default 10;
String name();
}
通过javap -v -p TA.class
命令查看字节码内容:
Last modified 2021-12-26; size 241 bytes
MD5 checksum 93aee1f6a305f95e0e48b05bdf959a51
Compiled from "TA.java"
public interface com.zhang.bytecode.proxy.TA extends java.lang.annotation.Annotation
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
Constant pool:
#1 = Class #12 // com/zhang/bytecode/proxy/TA
#2 = Class #13 // java/lang/Object
#3 = Class #14 // java/lang/annotation/Annotation
#4 = Utf8 age
#5 = Utf8 ()I
#6 = Utf8 AnnotationDefault
#7 = Integer 10
#8 = Utf8 name
#9 = Utf8 ()Ljava/lang/String;
#10 = Utf8 SourceFile
#11 = Utf8 TA.java
#12 = Utf8 com/zhang/bytecode/proxy/TA
#13 = Utf8 java/lang/Object
#14 = Utf8 java/lang/annotation/Annotation
{
public abstract int age();
descriptor: ()I
flags: ACC_PUBLIC, ACC_ABSTRACT
AnnotationDefault:
default_value: I#7
public abstract java.lang.String name();
descriptor: ()Ljava/lang/String;
flags: ACC_PUBLIC, ACC_ABSTRACT
}
SourceFile: "TA.java"
通过
public interface com.zhang.bytecode.proxy.TA extends java.lang.annotation.Annotation
;我们知道注解TA
是一个接口,而且是Annotation
的子接口。
2.8.2 注解实例
那我们就有疑惑,我们怎么获取到注解实例的呢?
例如:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
public @interface TA {
int age() default 10;
String name();
}
public class T {
@TA(name = "zhang")
public String field;
}
public static void main(String[] args) throws Exception {
Field field = T.class.getDeclaredField("field");
TA ta = field.getAnnotation(TA.class);
System.out.println(String.format("TA age[%s] name[%s] class[%s]",
ta.age(), ta.name(), ta.getClass()));
}
运行结果就是
TA age[10] name[zhang] class[class com.sun.proxy.$Proxy1]
很明显我们获取了注解
TA
的实例,这个实例的类名是class com.sun.proxy.$Proxy1
,这一眼就知道了,它是一个动态代理类名。
2.8.3 getAnnotation
方法
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
return annotationClass.cast(declaredAnnotations().get(annotationClass));
}
private Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
Map<Class<? extends Annotation>, Annotation> declAnnos;
if ((declAnnos = declaredAnnotations) == null) {
synchronized (this) {
if ((declAnnos = declaredAnnotations) == null) {
Field root = this.root;
if (root != null) {
declAnnos = root.declaredAnnotations();
} else {
declAnnos = AnnotationParser.parseAnnotations(
annotations,
sun.misc.SharedSecrets.getJavaLangAccess()
.getConstantPool(getDeclaringClass()),
getDeclaringClass());
}
declaredAnnotations = declAnnos;
}
}
}
return declAnnos;
}
主要还是看
AnnotationParser.parseAnnotations(...)
方法获取注解实例。
2.8.4 AnnotationParser.parseAnnotations(...)
方法
public static Map<Class<? extends Annotation>, Annotation> parseAnnotations(
byte[] rawAnnotations,
ConstantPool constPool,
Class<?> container) {
if (rawAnnotations == null)
return Collections.emptyMap();
try {
return parseAnnotations2(rawAnnotations, constPool, container, null);
} catch(BufferUnderflowException e) {
throw new AnnotationFormatError("Unexpected end of annotations.");
} catch(IllegalArgumentException e) {
// Type mismatch in constant pool
throw new AnnotationFormatError(e);
}
}
调用
parseAnnotations2(...)
方法生成注解实例。
private static Map<Class<? extends Annotation>, Annotation> parseAnnotations2(
byte[] rawAnnotations,
ConstantPool constPool,
Class<?> container,
Class<? extends Annotation>[] selectAnnotationClasses) {
Map<Class<? extends Annotation>, Annotation> result =
new LinkedHashMap<Class<? extends Annotation>, Annotation>();
ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
int numAnnotations = buf.getShort() & 0xFFFF;
for (int i = 0; i < numAnnotations; i++) {
Annotation a = parseAnnotation2(buf, constPool, container, false, selectAnnotationClasses);
if (a != null) {
Class<? extends Annotation> klass = a.annotationType();
if (AnnotationType.getInstance(klass).retention() == RetentionPolicy.RUNTIME &&
result.put(klass, a) != null) {
throw new AnnotationFormatError(
"Duplicate annotation for class: "+klass+": " + a);
}
}
}
return result;
}
通过
parseAnnotation2(...)
方法生成单个注解实例。
private static Annotation parseAnnotation2(ByteBuffer buf,
ConstantPool constPool,
Class<?> container,
boolean exceptionOnMissingAnnotationClass,
Class<? extends Annotation>[] selectAnnotationClasses) {
int typeIndex = buf.getShort() & 0xFFFF;
Class<? extends Annotation> annotationClass = null;
String sig = "[unknown]";
try {
try {
sig = constPool.getUTF8At(typeIndex);
annotationClass = (Class<? extends Annotation>)parseSig(sig, container);
} catch (IllegalArgumentException ex) {
// support obsolete early jsr175 format class files
annotationClass = (Class<? extends Annotation>)constPool.getClassAt(typeIndex);
}
} catch (NoClassDefFoundError e) {
if (exceptionOnMissingAnnotationClass)
// note: at this point sig is "[unknown]" or VM-style
// name instead of a binary name
throw new TypeNotPresentException(sig, e);
skipAnnotation(buf, false);
return null;
}
catch (TypeNotPresentException e) {
if (exceptionOnMissingAnnotationClass)
throw e;
skipAnnotation(buf, false);
return null;
}
if (selectAnnotationClasses != null && !contains(selectAnnotationClasses, annotationClass)) {
skipAnnotation(buf, false);
return null;
}
AnnotationType type = null;
try {
type = AnnotationType.getInstance(annotationClass);
} catch (IllegalArgumentException e) {
skipAnnotation(buf, false);
return null;
}
Map<String, Class<?>> memberTypes = type.memberTypes();
Map<String, Object> memberValues =
new LinkedHashMap<String, Object>(type.memberDefaults());
int numMembers = buf.getShort() & 0xFFFF;
for (int i = 0; i < numMembers; i++) {
int memberNameIndex = buf.getShort() & 0xFFFF;
String memberName = constPool.getUTF8At(memberNameIndex);
Class<?> memberType = memberTypes.get(memberName);
if (memberType == null) {
// Member is no longer present in annotation type; ignore it
skipMemberValue(buf);
} else {
Object value = parseMemberValue(memberType, buf, constPool, container);
if (value instanceof AnnotationTypeMismatchExceptionProxy)
((AnnotationTypeMismatchExceptionProxy) value).
setMember(type.members().get(memberName));
memberValues.put(memberName, value);
}
}
return annotationForMap(annotationClass, memberValues);
}
方法流程:
- 先获取注解的
Class
对象annotationClass
。 - 通过
annotationClass
获取AnnotationType
类型实例type
,里面包含着注解类所有方法,方法默认返回值和设置的方法返回值。例如
@TA(name = "zhang")
,这个注解的方法有两个age()
和name()
, 对应的值是10
和zhang
。 - 通过
AnnotationType
类型实例type
构建集合memberValues
,包含这个注解的所有方法和对应的返回值。 - 通过
annotationForMap(annotationClass, memberValues)
方法生成注解实例。
public static Annotation annotationForMap(final Class<? extends Annotation> type,
final Map<String, Object> memberValues)
{
return AccessController.doPrivileged(new PrivilegedAction<Annotation>() {
public Annotation run() {
return (Annotation) Proxy.newProxyInstance(
type.getClassLoader(), new Class<?>[] { type },
new AnnotationInvocationHandler(type, memberValues));
}});
}
通过
Proxy
生成注解的动态代理实例,传递一个AnnotationInvocationHandler
对象。
2.8.5 AnnotationInvocationHandler
类
public Object invoke(Object proxy, Method method, Object[] args) {
String member = method.getName();
Class<?>[] paramTypes = method.getParameterTypes();
// Handle Object and Annotation methods
if (member.equals("equals") && paramTypes.length == 1 &&
paramTypes[0] == Object.class)
return equalsImpl(args[0]);
if (paramTypes.length != 0)
throw new AssertionError("Too many parameters for an annotation method");
switch(member) {
case "toString":
return toStringImpl();
case "hashCode":
return hashCodeImpl();
case "annotationType":
return type;
}
// Handle annotation member accessors
Object result = memberValues.get(member);
if (result == null)
throw new IncompleteAnnotationException(type, member);
if (result instanceof ExceptionProxy)
throw ((ExceptionProxy) result).generateException();
if (result.getClass().isArray() && Array.getLength(result) != 0)
result = cloneArray(result);
return result;
}
你会发现调用注解代理类实例注解方法的时候,会通过方法名直接从
memberValues
中获取结果值。
三. cglib
代理原理
3.1 ClassGenerator
类
import org.objectweb.asm.ClassVisitor;
public interface ClassGenerator {
void generateClass(ClassVisitor v) throws Exception;
}
cglib
所有类生成器的接口,只有一个方法generateClass(ClassVisitor v)
,通过 ASM
的ClassVisitor
实例来生成类。
3.2 AbstractClassGenerator
类
所有cglib
类生成器的抽象基类,提供了缓存功能缓存生成的字节码文件来提高效率,还提供了各种各样的构造,让使用者定制类加载器 ClassLoader
,生成的类的名称以及在生成之前应用的转换。
3.2.1 重要属性
private static volatile Map<ClassLoader, ClassLoaderData> CACHE = new WeakHashMap<ClassLoader, ClassLoaderData>();
private GeneratorStrategy strategy = DefaultGeneratorStrategy.INSTANCE;
CACHE
缓存类加载器ClassLoader
生成的所有代理类数据ClassLoaderData
。
strategy
是代理类的生成策略。
3.2.2 create(Object key)
方法
protected Object create(Object key) {
try {
ClassLoader loader = getClassLoader();
Map<ClassLoader, ClassLoaderData> cache = CACHE;
ClassLoaderData data = cache.get(loader);
if (data == null) {
synchronized (AbstractClassGenerator.class) {
cache = CACHE;
data = cache.get(loader);
if (data == null) {
Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
data = new ClassLoaderData(loader);
newCache.put(loader, data);
CACHE = newCache;
}
}
}
this.key = key;
Object obj = data.get(this, getUseCache());
if (obj instanceof Class) {
return firstInstance((Class) obj);
}
return nextInstance(obj);
} catch (RuntimeException e) {
throw e;
} catch (Error e) {
throw e;
} catch (Exception e) {
throw new CodeGenerationException(e);
}
}
方法流程主要分为两步:
- 根据类加载器
ClassLoader
从缓存CACHE
获取对应的ClassLoaderData
实例。如果没有对应的
ClassLoaderData
实例,那么就创建它,并放到缓存中。 - 通过
ClassLoaderData
实例的data.get(this, getUseCache())
获取代理类Class
或者代理类实例。
3.2.3 ClassLoaderData
类
private final LoadingCache<AbstractClassGenerator, Object, Object> generatedClasses;
private final WeakReference<ClassLoader> classLoader;
private static final Function<AbstractClassGenerator, Object> GET_KEY = new Function<AbstractClassGenerator, Object>() {
public Object apply(AbstractClassGenerator gen) {
return gen.key;
}
};
public ClassLoaderData(ClassLoader classLoader) {
if (classLoader == null) {
throw new IllegalArgumentException("classLoader == null is not yet supported");
}
this.classLoader = new WeakReference<ClassLoader>(classLoader);
Function<AbstractClassGenerator, Object> load =
new Function<AbstractClassGenerator, Object>() {
public Object apply(AbstractClassGenerator gen) {
Class klass = gen.generate(ClassLoaderData.this);
return gen.wrapCachedClass(klass);
}
};
generatedClasses = new LoadingCache<AbstractClassGenerator, Object, Object>(GET_KEY, load);
}
构造方法流程:
- 使用弱引用
WeakReference
类型的classLoader
保存传进来的类加载器。 - 创建缓存
generatedClasses
值的生成器load
。通过类生成器
AbstractClassGenerator
的gen.generate(ClassLoaderData.this)
方法生成代理类Class
。 - 缓存
generatedClasses
键的生成器GET_KEY
。就是返回类生成器
AbstractClassGenerator
的成员变量gen.key
,在create(Object key)
方法中赋值。 - 最后创建
LoadingCache
类型缓存实例generatedClasses
。缓存
generatedClasses
作用就是存储类生成器AbstractClassGenerator
所有生成的代理类Class
。
public Object get(AbstractClassGenerator gen, boolean useCache) {
if (!useCache) {
return gen.generate(ClassLoaderData.this);
} else {
Object cachedValue = generatedClasses.get(gen);
return gen.unwrapCachedValue(cachedValue);
}
}
- 如果不使用缓存,那么就通过类生成器
AbstractClassGenerator
的gen.generate(ClassLoaderData.this)
方法生成代理类Class
。- 如果使用缓存,那么就从缓存
generatedClasses
中查找,如果存在那么就返回,不存在就通过缓存值的生成器load
创建。
3.2.4 generate(ClassLoaderData data)
方法
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.");
}
synchronized (classLoader) {
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);
}
}
方法流程:
- 先判断类加载器
classLoader
是否还存在,不存在就直接报错。 - 通过
generateClassName(...)
方法生成代理类的名字。 - 如果
attemptLoad
是true
,尝试通过类名从类加载器classLoader
中加载代理类Class
,如果有就直接返回了。 - 通过
strategy.generate(this)
生成代理类的字节数据。 - 最后将生成的代理类字节数据通过类加载器
classLoader
加载。
3.2.5 DefaultGeneratorStrategy
类
public class DefaultGeneratorStrategy implements GeneratorStrategy {
public static final DefaultGeneratorStrategy INSTANCE = new DefaultGeneratorStrategy();
public byte[] generate(ClassGenerator cg) throws Exception {
DebuggingClassWriter cw = getClassVisitor();
transform(cg).generateClass(cw);
return transform(cw.toByteArray());
}
protected DebuggingClassWriter getClassVisitor() throws Exception {
return new DebuggingClassWriter(ClassWriter.COMPUTE_FRAMES);
}
protected final ClassWriter getClassWriter() {
// Cause compile / runtime errors for people who implemented the old
// interface without using @Override
throw new UnsupportedOperationException("You are calling " +
"getClassWriter, which no longer exists in this cglib version.");
}
protected byte[] transform(byte[] b) throws Exception {
return b;
}
protected ClassGenerator transform(ClassGenerator cg) throws Exception {
return cg;
}
}
GeneratorStrategy
默认实现类DefaultGeneratorStrategy
非常简单,就是创建 DebuggingClassWriter
实例来接收类生成器实例cg
传递的数据,生成代理类字节码文件。
3.3 KeyFactory
类
先介绍KeyFactory
类的功能,在cglib
中经常用到它,它的主要功能就是生成特定接口实例。
不要惊讶,它肯定是生成了接口的实现代理类,然后创建这个代理类的实例赋值给接口实例。
3.3.1 静态创建方法
public static KeyFactory create(Class keyInterface) {
return create(keyInterface, null);
}
public static KeyFactory create(Class keyInterface, Customizer customizer) {
return create(keyInterface.getClassLoader(), keyInterface, customizer);
}
public static KeyFactory create(Class keyInterface, KeyFactoryCustomizer first, List<KeyFactoryCustomizer> next) {
return create(keyInterface.getClassLoader(), keyInterface, first, next);
}
public static KeyFactory create(ClassLoader loader, Class keyInterface, Customizer customizer) {
return create(loader, keyInterface, customizer, Collections.<KeyFactoryCustomizer>emptyList());
}
public static KeyFactory create(ClassLoader loader, Class keyInterface, KeyFactoryCustomizer customizer,
List<KeyFactoryCustomizer> next) {
Generator gen = new Generator();
gen.setInterface(keyInterface);
if (customizer != null) {
gen.addCustomizer(customizer);
}
if (next != null && !next.isEmpty()) {
for (KeyFactoryCustomizer keyFactoryCustomizer : next) {
gen.addCustomizer(keyFactoryCustomizer);
}
}
gen.setClassLoader(loader);
return gen.create();
}
传递一个接口的
Class
对象,然后创建KeyFactory.Generator
类生成器实例,最后通过类生成器生成KeyFactory
实例并返回。
3.3.2 KeyFactory.Generator
类
KeyFactory.Generator
继承自 AbstractClassGenerator
类。
public KeyFactory create() {
setNamePrefix(keyInterface.getName());
return (KeyFactory)super.create(keyInterface.getName());
}
使用接口名当生成接口代理类的唯一键。
下面就是重点分析 generateClass(ClassVisitor v)` 方法了
public void generateClass(ClassVisitor v) {
ClassEmitter ce = new ClassEmitter(v);
Method newInstance = ReflectUtils.findNewInstance(keyInterface);
if (!newInstance.getReturnType().equals(Object.class)) {
throw new IllegalArgumentException("newInstance method must return Object");
}
.......
}
通过ClassVisitor
实例创建 ClassEmitter
对象,ClassEmitter
是 cglib
提供的工具类,更方便生成字节码数据。
接口必须有 newInstance
方法,而且返回值必须是 Object
类型。
public void generateClass(ClassVisitor v) {
.......
Type[] parameterTypes =
TypeUtils.getTypes(newInstance.getParameterTypes());
ce.begin_class(Constants.V1_8,
Constants.ACC_PUBLIC,
getClassName(),
KEY_FACTORY,
new Type[]{ Type.getType(keyInterface) },
Constants.SOURCE_FILE);
EmitUtils.null_constructor(ce);
EmitUtils.factory_method(ce, ReflectUtils.getSignature(newInstance));
.......
}
通过 ClassEmitter
对象生成空参构造方法和接口类的方法等等。
3.3.3 示例
public class KeySample {
private interface MyFactory {
public Object newInstance(int a, char[] b, String d);
}
public static void main(String[] args) {
MyFactory f = (MyFactory)KeyFactory.create(MyFactory.class);
Object key1 = f.newInstance(20, new char[]{ 'a', 'b' }, "hello");
Object key2 = f.newInstance(20, new char[]{ 'a', 'b' }, "hello");
Object key3 = f.newInstance(20, new char[]{ 'a', '_' }, "hello");
System.out.println(key1.equals(key2));
System.out.println(key2.equals(key3));
}
}
运行结果如下:
true
false
生成代理类如下:
public class KeySample$MyFactory$$KeyFactoryByCGLIB$$a267b627 extends KeyFactory implements MyFactory {
private final int FIELD_0;
private final char[] FIELD_1;
private final String FIELD_2;
public KeySample$MyFactory$$KeyFactoryByCGLIB$$a267b627() {
}
public Object newInstance(int var1, char[] var2, String var3) {
return new KeySample$MyFactory$$KeyFactoryByCGLIB$$a267b627(var1, var2, var3);
}
public KeySample$MyFactory$$KeyFactoryByCGLIB$$a267b627(int var1, char[] var2, String var3) {
this.FIELD_0 = var1;
this.FIELD_1 = var2;
this.FIELD_2 = var3;
}
public int hashCode() {
int var10000 = 179 * 467063 + this.FIELD_0;
char[] var10001 = this.FIELD_1;
if (var10001 != null) {
char[] var1 = var10001;
for(int var2 = 0; var2 < var1.length; ++var2) {
var10000 = var10000 * 467063 + var1[var2];
}
}
int var10002 = var10000 * 467063;
String var3 = this.FIELD_2;
return var10002 + (var3 != null ? var3.hashCode() : 0);
}
public boolean equals(Object var1) {
if (var1 instanceof KeySample$MyFactory$$KeyFactoryByCGLIB$$a267b627 && this.FIELD_0 == ((KeySample$MyFactory$$KeyFactoryByCGLIB$$a267b627)var1).FIELD_0) {
char[] var10000 = this.FIELD_1;
char[] var10001 = ((KeySample$MyFactory$$KeyFactoryByCGLIB$$a267b627)var1).FIELD_1;
if (var10001 == null) {
if (var10000 != null) {
return false;
}
} else {
label71: {
if (var10000 != null) {
if (var10001.length == var10000.length) {
char[] var2 = var10001;
char[] var3 = var10000;
int var4 = 0;
while(true) {
if (var4 >= var2.length) {
break label71;
}
if (var2[var4] != var3[var4]) {
return false;
}
++var4;
}
}
}
return false;
}
}
String var5 = this.FIELD_2;
String var6 = ((KeySample$MyFactory$$KeyFactoryByCGLIB$$a267b627)var1).FIELD_2;
if (var6 == null) {
if (var5 == null) {
return true;
}
} else if (var5 != null && var5.equals(var6)) {
return true;
}
}
return false;
}
public String toString() {
StringBuffer var10000 = (new StringBuffer()).append(this.FIELD_0).append(", ");
char[] var10001 = this.FIELD_1;
if (var10001 != null) {
var10000 = var10000.append("{");
char[] var1 = var10001;
for(int var2 = 0; var2 < var1.length; ++var2) {
var10000 = var10000.append(var1[var2]).append(", ");
}
var10000.setLength(var10000.length() - 2);
var10000 = var10000.append("}");
} else {
var10000 = var10000.append("null");
}
var10000 = var10000.append(", ");
String var5 = this.FIELD_2;
return (var5 != null ? var10000.append(var5.toString()) : var10000.append("null")).toString();
}
}
我们发现这个代理类有如下特点:
- 居然继承自
KeyFactory
类,实现了传递的MyFactory
接口。 - 实现
newInstance
方法,返回当前代理类的实例,也是MyFactory
接口的实例。 - 复写了
hashCode
和equals
方法,保证了如果参数相同,那么两个实例就是相同的。
KeyFactory
的作用就是创建Key
值,生成代理类已经帮我们实现了 hashCode
和 equals
相等方法,而且它没有使用反射创建实例,速度还是非常快的。
3.4 Enhancer
类
3.4.1 create
方法
public Object create() {
classOnly = false;
argumentTypes = null;
return createHelper();
}
private Object createHelper() {
preValidate();
Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
ReflectUtils.getNames(interfaces),
filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter),
callbackTypes,
useFactory,
interceptDuringConstruction,
serialVersionUID);
this.currentKey = key;
Object result = super.create(key);
return result;
}
主要就两个步骤:
- 通过
KEY_FACTORY
获取要生成代理类的唯一Key
值。 - 调用
AbstractClassGenerator
的create(Object key)
获取代理类实例。
private static final EnhancerKey KEY_FACTORY =
(EnhancerKey)KeyFactory.create(EnhancerKey.class, KeyFactory.HASH_ASM_TYPE, null);
public interface EnhancerKey {
public Object newInstance(String type,
String[] interfaces,
WeakCacheKey<CallbackFilter> filter,
Type[] callbackTypes,
boolean useFactory,
boolean interceptDuringConstruction,
Long serialVersionUID);
}
可以看出 Enhancer
生成的代理类需要的唯一 Key
值,一共包含7
个参数。
3.4.2 generateClass(ClassVisitor v)
方法
public void generateClass(ClassVisitor v) throws Exception {
Class sc = (superclass == null) ? Object.class : superclass;
if (TypeUtils.isFinal(sc.getModifiers()))
throw new IllegalArgumentException("Cannot subclass final class " + sc.getName());
List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors()));
filterConstructors(sc, constructors);
.......
}
superclass
有值,表示代理类;superclass
没有值,那么只是代理接口。- 代理类的父类
superclass
访问标志不能是final
的。- 获取父类
superclass
的构造函数。
public void generateClass(ClassVisitor v) throws Exception {
.......
List actualMethods = new ArrayList();
List interfaceMethods = new ArrayList();
final Set forcePublic = new HashSet();
getMethods(sc, interfaces, actualMethods, interfaceMethods, forcePublic);
List methods = CollectionUtils.transform(actualMethods, new Transformer() {
public Object transform(Object value) {
Method method = (Method)value;
int modifiers = Constants.ACC_FINAL
| (method.getModifiers()
& ~Constants.ACC_ABSTRACT
& ~Constants.ACC_NATIVE
& ~Constants.ACC_SYNCHRONIZED);
if (forcePublic.contains(MethodWrapper.create(method))) {
modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC;
}
return ReflectUtils.getMethodInfo(method, modifiers);
}
});
.......
}
- 通过
getMethods(...)
得到代理类应该有的所有方法。- 通过
Transformer()
将方法转成MethodInfo
对象。
public void generateClass(ClassVisitor v) throws Exception {
.......
ClassEmitter e = new ClassEmitter(v);
if (currentData == null) {
e.begin_class(Constants.V1_8,
Constants.ACC_PUBLIC,
getClassName(),
Type.getType(sc),
(useFactory ?
TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) :
TypeUtils.getTypes(interfaces)),
Constants.SOURCE_FILE);
} else {
e.begin_class(Constants.V1_8,
Constants.ACC_PUBLIC,
getClassName(),
null,
new Type[]{FACTORY},
Constants.SOURCE_FILE);
}
List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());
.......
}
通过
ClassEmitter
实例创建代理类的字节码文件数据。
3.4.3 示例
public class Test {
public static void main(String[] args) {
final TI target = new T();
Enhancer e = new Enhancer();
e.setSuperclass(T.class);
e.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
long start = System.currentTimeMillis();
// methodProxy.invoke(target, objects);
System.out.println("一共花费了:"+ (System.currentTimeMillis() - start) +"毫秒");
return null;
}
});
T proxy = (T) e.create();
proxy.play();
}
}
注意这里将
methodProxy.invoke(target, objects);
这行注释了,这个后面再说。
会生成三个代理类文件:
-
EnhancerKey
的代理类public class Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72 extends KeyFactory implements EnhancerKey { private final String FIELD_0; private final String[] FIELD_1; private final WeakCacheKey FIELD_2; private final Type[] FIELD_3; private final boolean FIELD_4; private final boolean FIELD_5; private final Long FIELD_6; public Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72() { } public Object newInstance(String var1, String[] var2, WeakCacheKey var3, Type[] var4, boolean var5, boolean var6, Long var7) { return new Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72(var1, var2, var3, var4, var5, var6, var7); } public Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72(String var1, String[] var2, WeakCacheKey var3, Type[] var4, boolean var5, boolean var6, Long var7) { this.FIELD_0 = var1; this.FIELD_1 = var2; this.FIELD_2 = var3; this.FIELD_3 = var4; this.FIELD_4 = var5; this.FIELD_5 = var6; this.FIELD_6 = var7; } public int hashCode() { ...... } public int equals(Object var1) { ...... } public int toString() { ...... }
这个是
Enhancer
中KEY_FACTORY
字段生成的。 -
MethodWrapperKey
的代理类public class MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7 extends KeyFactory implements MethodWrapperKey { private final String FIELD_0; private final String[] FIELD_1; private final String FIELD_2; public MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7() { } public Object newInstance(String var1, String[] var2, String var3) { return new MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7(var1, var2, var3); } public MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7(String var1, String[] var2, String var3) { this.FIELD_0 = var1; this.FIELD_1 = var2; this.FIELD_2 = var3; } public int hashCode() { ...... } public int equals(Object var1) { ...... } public int toString() { ...... }
这个是
MethodWrapper
类中的KEY_FACTORY
生成的。在Enhancer
类的generateClass(ClassVisitor v)
方法中会调用到MethodWrapper.create(method)
方法。 -
目标类的代理类
public class T$$EnhancerByCGLIB$$422fccc9 extends T implements Factory { private boolean CGLIB$BOUND; public static Object CGLIB$FACTORY_DATA; private static final ThreadLocal CGLIB$THREAD_CALLBACKS; private static final Callback[] CGLIB$STATIC_CALLBACKS; private MethodInterceptor CGLIB$CALLBACK_0; private static Object CGLIB$CALLBACK_FILTER; private static final Method CGLIB$play$0$Method; private static final MethodProxy CGLIB$play$0$Proxy; private static final Object[] CGLIB$emptyArgs; private static final Method CGLIB$equals$1$Method; private static final MethodProxy CGLIB$equals$1$Proxy; private static final Method CGLIB$toString$2$Method; private static final MethodProxy CGLIB$toString$2$Proxy; private static final Method CGLIB$hashCode$3$Method; private static final MethodProxy CGLIB$hashCode$3$Proxy; private static final Method CGLIB$clone$4$Method; private static final MethodProxy CGLIB$clone$4$Proxy; } public final void play() { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if (var10000 != null) { var10000.intercept(this, CGLIB$play$0$Method, CGLIB$emptyArgs, CGLIB$play$0$Proxy); } else { super.play(); } }
- 代理类继承自目标类,而且实现了
Factory
接口。 - 可以看到
play()
方法,会调用MethodInterceptor
实例的intercept
方法。
- 代理类继承自目标类,而且实现了
如果我们调用 methodProxy.invoke(target, objects);
方法,会发现又生成两个代理类,这个就是我们接下来就讲解的MethodProxy
类。
3.5 MethodProxy
类
3.5.1 invoke
方法
public Object invoke(Object obj, Object[] args) throws Throwable {
try {
init();
FastClassInfo fci = fastClassInfo;
return fci.f1.invoke(fci.i1, obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (IllegalArgumentException e) {
if (fastClassInfo.i1 < 0)
throw new IllegalArgumentException("Protected method: " + sig1);
throw e;
}
}
- 先调用
init()
进行初始化。- 然后调用
fci.f1.invoke(fci.i1, obj, args)
调用目标方法。
3.5.2 init()
方法
private void init()
{
if (fastClassInfo == null)
{
synchronized (initLock)
{
if (fastClassInfo == null)
{
CreateInfo ci = createInfo;
FastClassInfo fci = new FastClassInfo();
fci.f1 = helper(ci, ci.c1);
fci.f2 = helper(ci, ci.c2);
fci.i1 = fci.f1.getIndex(sig1);
fci.i2 = fci.f2.getIndex(sig2);
fastClassInfo = fci;
createInfo = null;
}
}
}
}
private static class FastClassInfo
{
FastClass f1;
FastClass f2;
int i1;
int i2;
}
当 fastClassInfo
没有值的时候,就会创建它;fastClassInfo
中有四个属性:
-
f1
和i1
: 代表目标类实例对应快速调用类FastClass
。 -
f2
和i2
: 代表代理类实例对应快速调用类FastClass
。
3.5.3 helper(...)
方法
private static FastClass helper(CreateInfo ci, Class type) {
FastClass.Generator g = new FastClass.Generator();
g.setType(type);
g.setClassLoader(ci.c2.getClassLoader());
g.setNamingPolicy(ci.namingPolicy);
g.setStrategy(ci.strategy);
g.setAttemptLoad(ci.attemptLoad);
return g.create();
}
就是通过
FastClass.Generator
类生成器生成FastClass
代理类。
3.5.4 FastClass.Generator
类
public FastClass create() {
setNamePrefix(type.getName());
return (FastClass)super.create(type.getName());
}
通过
AbstractClassGenerator
的create
方法生成代理类。
public void generateClass(ClassVisitor v) throws Exception {
new FastClassEmitter(v, getClassName(), type);
}
主要靠
FastClassEmitter
类来生成字节码文件。
3.5.5 FastClassEmitter
类
public FastClassEmitter(ClassVisitor v, String className, Class type) {
super(v);
Type base = Type.getType(type);
begin_class(Constants.V1_8, Constants.ACC_PUBLIC, className, FAST_CLASS, null, Constants.SOURCE_FILE);
// constructor
CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_CLASS, null);
e.load_this();
e.load_args();
e.super_invoke_constructor(CSTRUCT_CLASS);
e.return_value();
e.end_method();
......
}
也是通过
CodeEmitter
来生成字节码文件。
3.5.6 生成的代理类
public class T$$FastClassByCGLIB$$3ad7f32f extends FastClass {
public T$$FastClassByCGLIB$$3ad7f32f(Class var1) {
super(var1);
}
public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
case -493628479:
if (var10000.equals("play()V")) {
return 0;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return 1;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return 2;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return 3;
}
}
return -1;
}
public int getIndex(String var1, Class[] var2) {
switch(var1.hashCode()) {
case -1776922004:
if (var1.equals("toString")) {
switch(var2.length) {
case 0:
return 2;
}
}
break;
case -1295482945:
if (var1.equals("equals")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.Object")) {
return 1;
}
}
}
break;
case 3443508:
if (var1.equals("play")) {
switch(var2.length) {
case 0:
return 0;
}
}
break;
case 147696667:
if (var1.equals("hashCode")) {
switch(var2.length) {
case 0:
return 3;
}
}
}
return -1;
}
public int getIndex(Class[] var1) {
switch(var1.length) {
case 0:
return 0;
default:
return -1;
}
}
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
T var10000 = (T)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
var10000.play();
return null;
case 1:
return new Boolean(var10000.equals(var3[0]));
case 2:
return var10000.toString();
case 3:
return new Integer(var10000.hashCode());
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
T var10000 = new T;
T var10001 = var10000;
int var10002 = var1;
try {
switch(var10002) {
case 0:
var10001.<init>();
return var10000;
}
} catch (Throwable var3) {
throw new InvocationTargetException(var3);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public int getMaxIndex() {
return 3;
}
}
- 可以看到继承自
FastClass
类。- 最大的作用就是为目标类每个方法都设置了索引
index
,因此当调用目标实例方法时,那就可以直接使用目标实例调用方法,而不需要使用反射了。
public class T$$EnhancerByCGLIB$$422fccc9$$FastClassByCGLIB$$4e16ba3f extends FastClass {
public T$$EnhancerByCGLIB$$422fccc9$$FastClassByCGLIB$$4e16ba3f(Class var1) {
super(var1);
}
public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
case -2055565910:
if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
return 2;
}
break;
case -1882565338:
if (var10000.equals("CGLIB$equals$1(Ljava/lang/Object;)Z")) {
return 10;
}
break;
case -1457535688:
if (var10000.equals("CGLIB$STATICHOOK1()V")) {
return 8;
}
break;
case -1411842725:
if (var10000.equals("CGLIB$hashCode$3()I")) {
return 12;
}
break;
case -894172689:
if (var10000.equals("newInstance(Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 20;
}
break;
case -623122092:
if (var10000.equals("CGLIB$findMethodProxy(Lnet/sf/cglib/core/Signature;)Lnet/sf/cglib/proxy/MethodProxy;")) {
return 7;
}
break;
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return 17;
}
break;
case -493628479:
if (var10000.equals("play()V")) {
return 6;
}
break;
case -419626537:
if (var10000.equals("setCallbacks([Lnet/sf/cglib/proxy/Callback;)V")) {
return 0;
}
break;
case 560567118:
if (var10000.equals("setCallback(ILnet/sf/cglib/proxy/Callback;)V")) {
return 5;
}
break;
case 811063227:
if (var10000.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 19;
}
break;
case 973717575:
if (var10000.equals("getCallbacks()[Lnet/sf/cglib/proxy/Callback;")) {
return 4;
}
break;
case 1221173700:
if (var10000.equals("newInstance([Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 18;
}
break;
case 1230699260:
if (var10000.equals("getCallback(I)Lnet/sf/cglib/proxy/Callback;")) {
return 3;
}
break;
case 1306468936:
if (var10000.equals("CGLIB$toString$2()Ljava/lang/String;")) {
return 11;
}
break;
case 1584330438:
if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
return 1;
}
break;
case 1800494055:
if (var10000.equals("CGLIB$clone$4()Ljava/lang/Object;")) {
return 13;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return 14;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return 15;
}
break;
case 1937760082:
if (var10000.equals("CGLIB$play$0()V")) {
return 9;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return 16;
}
}
return -1;
}
......
}
这个是代理类所有方法的索引。
3.6 小结
cglib
代理方法调用为什么比动态代理快,就是因为cglib
代理会直接通过目标实例调用对应的方法,而动态代理只能通过反射方式。
但是如果使用 MethodProxy
方式调用,第一次的情况下,需要生成目标类和代理类的 FastClass
字节码文件,这个比较耗时。如果你只调用一次的话,那么使用 Method
直接反射调用。