Skip to main content

InvocationHandler 和动态代理

· 4 min read

背景

了解java的InvocationHandler

在Java中,Proxy.newProxyInstance 的实现以及动态生成的代理类的字节码是由Java的 ProxyGenerator 类完成的

介绍

动态代理主要包括两个部分

  • invocationHandler 接口 , 实现回调
  • Proxy.newInstance生成代理类

proxy.newInstance

1 获取过程是反射所有的接口 2 在生成byte[] 字符串,这个是class文件 3 生成代理类

  private static final class ProxyBuilder {
private static final Unsafe UNSAFE = Unsafe.getUnsafe();

// 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();

// a reverse cache of defined proxy classes
private static final ClassLoaderValue<Boolean> reverseProxyCache =
new ClassLoaderValue<>();

private static Class<?> defineProxyClass(Module m, List<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; // non-public, final
String pkg = intf.getPackageName();
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}

if (proxyPkg == null) {
// all proxy interfaces are public
proxyPkg = m.isNamed() ? PROXY_PACKAGE_PREFIX + "." + m.getName()
: PROXY_PACKAGE_PREFIX;
} else if (proxyPkg.isEmpty() && m.isNamed()) {
throw new IllegalArgumentException(
"Unnamed package cannot be added to " + m);
}

if (m.isNamed()) {
if (!m.getDescriptor().packages().contains(proxyPkg)) {
throw new InternalError(proxyPkg + " not exist in " + m.getName());
}
}

/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg.isEmpty()
? proxyClassNamePrefix + num
: proxyPkg + "." + proxyClassNamePrefix + num;

ClassLoader loader = getLoader(m);
trace(proxyName, m, loader, interfaces);

/*
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces.toArray(EMPTY_CLASS_ARRAY), accessFlags);
try {
Class<?> pc = UNSAFE.defineClass(proxyName, proxyClassFile,
0, proxyClassFile.length,
loader, null);
reverseProxyCache.sub(pc).putIfAbsent(loader, Boolean.TRUE);
return pc;
} 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());
}
}

相关堆栈:

proxyClassContext:844, Proxy$ProxyBuilder (java.lang.reflect)
<init>:638, Proxy$ProxyBuilder (java.lang.reflect)
<init>:643, Proxy$ProxyBuilder (java.lang.reflect)
lambda$getProxyConstructor$0:429, Proxy (java.lang.reflect)
apply:-1, Proxy$$Lambda/0x00007fd0dc066718 (java.lang.reflect)
get:329, AbstractClassLoaderValue$Memoizer (jdk.internal.loader)
computeIfAbsent:205, AbstractClassLoaderValue (jdk.internal.loader)
getProxyConstructor:427, Proxy (java.lang.reflect)
newProxyInstance:1034, Proxy (java.lang.reflect)
run:301, AnnotationParser$1 (sun.reflect.annotation)
run:299, AnnotationParser$1 (sun.reflect.annotation)
executePrivileged:778, AccessController (java.security)
doPrivileged:319, AccessController (java.security)
annotationForMap:299, AnnotationParser (sun.reflect.annotation)
parseAnnotation2:288, AnnotationParser (sun.reflect.annotation)
parseAnnotations2:121, AnnotationParser (sun.reflect.annotation)
parseSelectAnnotations:102, AnnotationParser (sun.reflect.annotation)
<init>:146, AnnotationType (sun.reflect.annotation)
getInstance:85, AnnotationType (sun.reflect.annotation)
parseAnnotation2:262, AnnotationParser (sun.reflect.annotation)
parseAnnotations2:121, AnnotationParser (sun.reflect.annotation)
parseAnnotations:73, AnnotationParser (sun.reflect.annotation)
createAnnotationData:4246, Class (java.lang)
annotationData:4235, Class (java.lang)
getDeclaredAnnotations:4202, Class (java.lang)
getDeclaredAnnotations:449, AnnotationsScanner (org.springframework.core.annotation)
processClassHierarchy:188, AnnotationsScanner (org.springframework.core.annotation)
processClassHierarchy:196, AnnotationsScanner (org.springframework.core.annotation)
processClassHierarchy:171, AnnotationsScanner (org.springframework.core.annotation)
processClass:108, AnnotationsScanner (org.springframework.core.annotation)
process:92, AnnotationsScanner (org.springframework.core.annotation)
scan:82, AnnotationsScanner (org.springframework.core.annotation)
scan:248, TypeMappedAnnotations (org.springframework.core.annotation)
get:155, TypeMappedAnnotations (org.springframework.core.annotation)
get:137, TypeMappedAnnotations (org.springframework.core.annotation)
findOrder:123, OrderUtils (org.springframework.core.annotation)
getOrderFromAnnotations:116, OrderUtils (org.springframework.core.annotation)
findOrderFromAnnotation:75, AnnotationAwareOrderComparator (org.springframework.core.annotation)
findOrder:68, AnnotationAwareOrderComparator (org.springframework.core.annotation)
getOrder:128, OrderComparator (org.springframework.core)
getOrder:116, OrderComparator (org.springframework.core)
doCompare:86, OrderComparator (org.springframework.core)
compare:73, OrderComparator (org.springframework.core)
countRunAndMakeAscending:355, TimSort (java.util)
sort:220, TimSort (java.util)
sort:1308, Arrays (java.util)
sort:1804, ArrayList (java.util)
sort:111, AnnotationAwareOrderComparator (org.springframework.core.annotation)
load:211, SpringFactoriesLoader (org.springframework.core.io.support)
load:160, SpringFactoriesLoader (org.springframework.core.io.support)
getSpringFactoriesInstances:482, SpringApplication (org.springframework.boot)
getSpringFactoriesInstances:478, SpringApplication (org.springframework.boot)
<init>:283, SpringApplication (org.springframework.boot)
<init>:262, SpringApplication (org.springframework.boot)
run:1342, SpringApplication (org.springframework.boot)
run:1331, SpringApplication (org.springframework.boot)
main:10, DemoApplication (com.example.demo)

相关阅读