java 1.8 动态代理源码深度分析
JDK8动态代理源码分析
动态代理的基本使用就不详细介绍了:
例子:
classproxyedimplementspro{
@Override
publicvoidtext(){
System.err.println("本方法");
}
}
interfacepro{
voidtext();
}
publicclassJavaProxyimplementsInvocationHandler{
privateObjectsource;
publicJavaProxy(Objectsource){
super();
this.source=source;
}
publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{
System.out.println("before");
Objectinvoke=method.invoke(source,args);
System.out.println("after");
returninvoke;
}
publicObjectgetProxy(){
returnProxy.newProxyInstance(getClass().getClassLoader(),source.getClass().getInterfaces(),this);
}
publicstaticvoidmain(String[]args)throwsIllegalAccessException,InvocationTargetException,InstantiationException,NoSuchMethodException{
//第一种,自己写
//1.设置saveGeneratedFiles值为true则生成class字节码文件方便分析
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
//2.获取动态代理类
ClassproxyClazz=Proxy.getProxyClass(pro.class.getClassLoader(),pro.class);
//3.获得代理类的构造函数,并传入参数类型InvocationHandler.class
Constructorconstructor=proxyClazz.getConstructor(InvocationHandler.class);
//4.通过构造函数来创建动态代理对象,将自定义的InvocationHandler实例传入
proiHello=(pro)constructor.newInstance(newJavaProxy(newproxyed()));
//5.通过代理对象调用目标方法
iHello.text();
//第二种,调用JDK提供的方法,实现了2~4步
Proxy.newProxyInstance(JavaProxy.class.getClassLoader(),proxyed.class.getInterfaces(),newJavaProxy(newproxyed()));
}
}
入口:newProxyInstance
publicstaticObjectnewProxyInstance(ClassLoaderloader,Class>[]interfaces,InvocationHandlerh)throwsIllegalArgumentException{
//Objects.requireNonNull判空方法,之后所有的单纯的判断null并抛异常,都是此方法
Objects.requireNonNull(h);
//clone类实现的所有接口
finalClass>[]intfs=interfaces.clone();
//获取当前系统安全接口
finalSecurityManagersm=System.getSecurityManager();
if(sm!=null){
//Reflection.getCallerClass返回调用该方法的方法的调用类;loader:接口的类加载器
//进行包访问权限、类加载器权限等检查
checkProxyAccess(Reflection.getCallerClass(),loader,intfs);
}
/*
*Lookuporgeneratethedesignatedproxyclass.
*查找或生成代理类
*/
Class>cl=getProxyClass0(loader,intfs);
/*
*Invokeitsconstructorwiththedesignatedinvocationhandler.
*使用指定的调用处理程序调用它的构造函数
*/
try{
if(sm!=null){
checkNewProxyPermission(Reflection.getCallerClass(),cl);
}
//获取构造
finalConstructor>cons=cl.getConstructor(constructorParams);
finalInvocationHandlerih=h;
if(!Modifier.isPublic(cl.getModifiers())){
AccessController.doPrivileged(newPrivilegedAction(){
publicVoidrun(){
cons.setAccessible(true);
returnnull;
}
});
}
//返回代理对象
returncons.newInstance(newObject[]{h});
}catch(IllegalAccessException|InstantiationExceptione){
thrownewInternalError(e.toString(),e);
}catch(InvocationTargetExceptione){
Throwablet=e.getCause();
if(tinstanceofRuntimeException){
throw(RuntimeException)t;
}else{
thrownewInternalError(t.toString(),t);
}
}catch(NoSuchMethodExceptione){
thrownewInternalError(e.toString(),e);
}
}
从上面的分析中可以看出,newProxyInstance帮我们执行了生成代理类----获取构造器----生成代理对象这三步;
我们重点分析生成代理类
getProxyClass0
/** *acacheofproxyclasses:动态代理类的弱缓存容器 *KeyFactory:根据接口的数量,映射一个最佳的key生成函数,其中表示接口的类对象被弱引用;也就是key对象被弱引用继承自WeakReference(key0、key1、key2、keyX),保存接口密钥(hash值) *ProxyClassFactory:生成动态类的工厂 *注意,两个都实现了BiFunction[],Object>接口 */ privatestaticfinalWeakCache [],Class>>proxyClassCache=newWeakCache<>(newKeyFactory(),newProxyClassFactory()); /** *Generateaproxyclass.MustcallthecheckProxyAccessmethod *toperformpermissionchecksbeforecallingthis. *生成代理类,调用前必须进行checkProxyAccess权限检查,所以newProxyInstance进行了权限检查 */ privatestaticClass>getProxyClass0(ClassLoaderloader,Class>...interfaces){ //实现接口的最大数量<65535;谁写的类能实现这么多接口 if(interfaces.length>65535){ thrownewIllegalArgumentException("interfacelimitexceeded"); } //Iftheproxyclassdefinedbythegivenloaderimplementing //thegiveninterfacesexists,thiswillsimplyreturnthecachedcopy; //otherwise,itwillcreatetheproxyclassviatheProxyClassFactory //如果缓存中有,就直接返回,否则会生成 returnproxyClassCache.get(loader,interfaces); }
proxyClassCache.get
publicVget(Kkey,Pparameter){
//key:类加载器;parameter:接口数组
Objects.requireNonNull(parameter);
//清除已经被GC回收的弱引用
expungeStaleEntries();
//CacheKey弱引用类,refQueue已经被回收的弱引用队列;构建一个CacheKey
ObjectcacheKey=CacheKey.valueOf(key,refQueue);
//map一级缓存,获取valuesMap二级缓存
ConcurrentMap
supplier.get
这个方法中会调用ProxyClassFactory的apply方法,就不过多介绍
ProxyClassFactory.apply
publicClass>apply(ClassLoaderloader,Class>[]interfaces){
Map,Boolean>interfaceSet=newIdentityHashMap<>(interfaces.length);
for(Class>intf:interfaces){
/*
*VerifythattheclassloaderresolvesthenameofthisinterfacetothesameClassobject.
*类加载器和接口名解析出的是同一个
*/
Class>interfaceClass=null;
try{
interfaceClass=Class.forName(intf.getName(),false,loader);
}catch(ClassNotFoundExceptione){
}
if(interfaceClass!=intf){
thrownewIllegalArgumentException(intf+"isnotvisiblefromclassloader");
}
/*
*VerifythattheClassobjectactuallyrepresentsaninterface.
*确保是一个接口
*/
if(!interfaceClass.isInterface()){
thrownewIllegalArgumentException(interfaceClass.getName()+"isnotaninterface");
}
/*
*Verifythatthisinterfaceisnotaduplicate.
*确保接口没重复
*/
if(interfaceSet.put(interfaceClass,Boolean.TRUE)!=null){
thrownewIllegalArgumentException("repeatedinterface:"+interfaceClass.getName());
}
}
StringproxyPkg=null;//packagetodefineproxyclassin
intaccessFlags=Modifier.PUBLIC|Modifier.FINAL;
/*
*Recordthepackageofanon-publicproxyinterfacesothattheproxyclasswillbedefinedinthesamepackage.
*Verifythatallnon-publicproxyinterfacesareinthesamepackage.
*验证所有非公共的接口在同一个包内;公共的就无需处理
*/
for(Class>intf:interfaces){
intflags=intf.getModifiers();
if(!Modifier.isPublic(flags)){
accessFlags=Modifier.FINAL;
Stringname=intf.getName();
intn=name.lastIndexOf('.');
Stringpkg=((n==-1)?"":name.substring(0,n+1));
if(proxyPkg==null){
proxyPkg=pkg;
}elseif(!pkg.equals(proxyPkg)){
thrownewIllegalArgumentException("non-publicinterfacesfromdifferentpackages");
}
}
}
if(proxyPkg==null){
//ifnonon-publicproxyinterfaces,usecom.sun.proxypackage
proxyPkg=ReflectUtil.PROXY_PACKAGE+".";
}
/*
*Chooseanamefortheproxyclasstogenerate.
*proxyClassNamePrefix=$Proxy
*nextUniqueNumber是一个原子类,确保多线程安全,防止类名重复,类似于:$Proxy0,$Proxy1......
*/
longnum=nextUniqueNumber.getAndIncrement();
StringproxyName=proxyPkg+proxyClassNamePrefix+num;
/*
*Generatethespecifiedproxyclass.
*生成类字节码的方法:重点
*/
byte[]proxyClassFile=ProxyGenerator.generateProxyClass(proxyName,interfaces,accessFlags);
try{
returndefineClass0(loader,proxyName,proxyClassFile,0,proxyClassFile.length);
}catch(ClassFormatErrore){
/*
*AClassFormatErrorheremeansthat(barringbugsinthe
*proxyclassgenerationcode)therewassomeother
*invalidaspectoftheargumentssuppliedtotheproxy
*classcreation(suchasvirtualmachinelimitations
*exceeded).
*/
thrownewIllegalArgumentException(e.toString());
}
}
ProxyGenerator.generateProxyClass
publicstaticbyte[]generateProxyClass(finalStringname,Class>[]interfaces,intaccessFlags){
ProxyGeneratorgen=newProxyGenerator(name,interfaces,accessFlags);
//真正生成字节码的方法
finalbyte[]classFile=gen.generateClassFile();
//如果saveGeneratedFiles为true则生成字节码文件,所以在开始我们要设置这个参数
//当然,也可以通过返回的bytes自己输出
if(saveGeneratedFiles){
java.security.AccessController.doPrivileged(newjava.security.PrivilegedAction(){
publicVoidrun(){
try{
inti=name.lastIndexOf('.');
Pathpath;
if(i>0){
Pathdir=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);
returnnull;
}catch(IOExceptione){
thrownewInternalError("I/Oexceptionsavinggeneratedfile:"+e);
}
}
});
}
returnclassFile;
}
最终方法
privatebyte[]generateClassFile(){
/*============================================================
*Step1:AssembleProxyMethodobjectsforallmethodstogenerateproxydispatchingcodefor.
*步骤1:为所有方法生成代理调度代码,将代理方法对象集合起来。
*/
//增加hashcode、equals、toString方法
addProxyMethod(hashCodeMethod,Object.class);
addProxyMethod(equalsMethod,Object.class);
addProxyMethod(toStringMethod,Object.class);
//增加接口方法
for(Class>intf:interfaces){
for(Methodm:intf.getMethods()){
addProxyMethod(m,intf);
}
}
/*
*验证方法签名相同的一组方法,返回值类型是否相同;意思就是重写方法要方法签名和返回值一样
*/
for(Listsigmethods:proxyMethods.values()){
checkReturnTypes(sigmethods);
}
/*============================================================
*Step2:AssembleFieldInfoandMethodInfostructsforalloffieldsandmethodsintheclasswearegenerating.
*为类中的方法生成字段信息和方法信息
*/
try{
//增加构造方法
methods.add(generateConstructor());
for(Listsigmethods:proxyMethods.values()){
for(ProxyMethodpm:sigmethods){
//addstaticfieldformethod'sMethodobject
fields.add(newFieldInfo(pm.methodFieldName,
"Ljava/lang/reflect/Method;",
ACC_PRIVATE|ACC_STATIC));
//generatecodeforproxymethodandaddit
methods.add(pm.generateMethod());
}
}
//增加静态初始化信息
methods.add(generateStaticInitializer());
}catch(IOExceptione){
thrownewInternalError("unexpectedI/OException",e);
}
if(methods.size()>65535){
thrownewIllegalArgumentException("methodlimitexceeded");
}
if(fields.size()>65535){
thrownewIllegalArgumentException("fieldlimitexceeded");
}
/*============================================================
*Step3:Writethefinalclassfile.
*步骤3:编写最终类文件
*/
/*
*Makesurethatconstantpoolindexesarereservedforthefollowingitemsbeforestartingtowritethefinalclassfile.
*在开始编写最终类文件之前,确保为下面的项目保留常量池索引。
*/
cp.getClass(dotToSlash(className));
cp.getClass(superclassName);
for(Class>intf:interfaces){
cp.getClass(dotToSlash(intf.getName()));
}
/*
*Disallownewconstantpooladditionsbeyondthispoint,sinceweareabouttowritethefinalconstantpooltable.
*设置只读,在这之前不允许在常量池中增加信息,因为要写常量池表
*/
cp.setReadOnly();
ByteArrayOutputStreambout=newByteArrayOutputStream();
DataOutputStreamdout=newDataOutputStream(bout);
try{
//u4magic;
dout.writeInt(0xCAFEBABE);
//u2次要版本;
dout.writeShort(CLASSFILE_MINOR_VERSION);
//u2主版本
dout.writeShort(CLASSFILE_MAJOR_VERSION);
cp.write(dout);//(writeconstantpool)
//u2访问标识;
dout.writeShort(accessFlags);
//u2本类名;
dout.writeShort(cp.getClass(dotToSlash(className)));
//u2父类名;
dout.writeShort(cp.getClass(superclassName));
//u2接口;
dout.writeShort(interfaces.length);
//u2interfaces[interfaces_count];
for(Class>intf:interfaces){
dout.writeShort(cp.getClass(
dotToSlash(intf.getName())));
}
//u2字段;
dout.writeShort(fields.size());
//field_infofields[fields_count];
for(FieldInfof:fields){
f.write(dout);
}
//u2方法;
dout.writeShort(methods.size());
//method_infomethods[methods_count];
for(MethodInfom:methods){
m.write(dout);
}
//u2类文件属性:对于代理类来说没有类文件属性;
dout.writeShort(0);//(noClassFileattributesforproxyclasses)
}catch(IOExceptione){
thrownewInternalError("unexpectedI/OException",e);
}
returnbout.toByteArray();
}
生成的字节码反编译
finalclass$Proxy0extendsProxyimplementspro{
//fields
privatestaticMethodm1;
privatestaticMethodm2;
privatestaticMethodm3;
privatestaticMethodm0;
public$Proxy0(InvocationHandlervar1)throws{
super(var1);
}
publicfinalbooleanequals(Objectvar1)throws{
try{
return((Boolean)super.h.invoke(this,m1,newObject[]{var1})).booleanValue();
}catch(RuntimeException|Errorvar3){
throwvar3;
}catch(Throwablevar4){
thrownewUndeclaredThrowableException(var4);
}
}
publicfinalStringtoString()throws{
try{
return(String)super.h.invoke(this,m2,(Object[])null);
}catch(RuntimeException|Errorvar2){
throwvar2;
}catch(Throwablevar3){
thrownewUndeclaredThrowableException(var3);
}
}
publicfinalvoidtext()throws{
try{
//实际就是调用代理类的invoke方法
super.h.invoke(this,m3,(Object[])null);
}catch(RuntimeException|Errorvar2){
throwvar2;
}catch(Throwablevar3){
thrownewUndeclaredThrowableException(var3);
}
}
publicfinalinthashCode()throws{
try{
return((Integer)super.h.invoke(this,m0,(Object[])null)).intValue();
}catch(RuntimeException|Errorvar2){
throwvar2;
}catch(Throwablevar3){
thrownewUndeclaredThrowableException(var3);
}
}
static{
try{
//这里每个方法对象和类的实际方法绑定
m1=Class.forName("java.lang.Object").getMethod("equals",newClass[]{Class.forName("java.lang.Object")});
m2=Class.forName("java.lang.Object").getMethod("toString",newClass[0]);
m3=Class.forName("spring.commons.api.study.CreateModel.pro").getMethod("text",newClass[0]);
m0=Class.forName("java.lang.Object").getMethod("hashCode",newClass[0]);
}catch(NoSuchMethodExceptionvar2){
thrownewNoSuchMethodError(var2.getMessage());
}catch(ClassNotFoundExceptionvar3){
thrownewNoClassDefFoundError(var3.getMessage());
}
}
}
以上这篇java1.8动态代理源码深度分析就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。