Mybatis懒加载的实现
因为通过javassist和cglib代理实现的,所以说到底最主要的就是JavasisstProxyFactory类中的invoke方法和里面的load方法。
其实读一读,里面的逻辑就是跟配置中定义的规则一样的
因为github上的mybatis中文版中这部分注释比较少,所以从网上寻找博客,截取了代码注释片段记录下。
JavasisstProxyFactory
publicclassJavassistProxyFactoryimplementsorg.apache.ibatis.executor.loader.ProxyFactory{
/**
*接口实现
*@paramtarget目标结果对象
*@paramlazyLoader延迟加载对象
*@paramconfiguration配置
*@paramobjectFactory对象工厂
*@paramconstructorArgTypes构造参数类型
*@paramconstructorArgs构造参数值
*@return
*/
@Override
publicObjectcreateProxy(Objecttarget,ResultLoaderMaplazyLoader,Configurationconfiguration,ObjectFactoryobjectFactory,List<Class<?>>constructorArgTypes,List<Object>constructorArgs){
returnEnhancedResultObjectProxyImpl.createProxy(target,lazyLoader,configuration,objectFactory,constructorArgTypes,constructorArgs);
}
//省略...
/**
*代理对象实现,核心逻辑执行
*/
privatestaticclassEnhancedResultObjectProxyImplimplementsMethodHandler{
/**
*创建代理对象
*@paramtype
*@paramcallback
*@paramconstructorArgTypes
*@paramconstructorArgs
*@return
*/
staticObjectcrateProxy(Class<?>type,MethodHandlercallback,List<Class<?>>constructorArgTypes,List<Object>constructorArgs){
ProxyFactoryenhancer=newProxyFactory();
enhancer.setSuperclass(type);
try{
//通过获取对象方法,判断是否存在该方法
type.getDeclaredMethod(WRITE_REPLACE_METHOD);
//ObjectOutputStreamwillcallwriteReplaceofobjectsreturnedbywriteReplace
if(log.isDebugEnabled()){
log.debug(WRITE_REPLACE_METHOD+"methodwasfoundonbean"+type+",makesureitreturnsthis");
}
}catch(NoSuchMethodExceptione){
//没找到该方法,实现接口
enhancer.setInterfaces(newClass[]{WriteReplaceInterface.class});
}catch(SecurityExceptione){
//nothingtodohere
}
Objectenhanced;
Class<?>[]typesArray=constructorArgTypes.toArray(newClass[constructorArgTypes.size()]);
Object[]valuesArray=constructorArgs.toArray(newObject[constructorArgs.size()]);
try{
//创建新的代理对象
enhanced=enhancer.create(typesArray,valuesArray);
}catch(Exceptione){
thrownewExecutorException("Errorcreatinglazyproxy.Cause:"+e,e);
}
//设置代理执行器
((Proxy)enhanced).setHandler(callback);
returnenhanced;
}
/**
*代理对象执行
*@paramenhanced原对象
*@parammethod原对象方法
*@parammethodProxy代理方法
*@paramargs方法参数
*@return
*@throwsThrowable
*/
@Override
publicObjectinvoke(Objectenhanced,Methodmethod,MethodmethodProxy,Object[]args)throwsThrowable{
finalStringmethodName=method.getName();
try{
synchronized(lazyLoader){
if(WRITE_REPLACE_METHOD.equals(methodName)){
//忽略暂未找到具体作用
Objectoriginal;
if(constructorArgTypes.isEmpty()){
original=objectFactory.create(type);
}else{
original=objectFactory.create(type,constructorArgTypes,constructorArgs);
}
PropertyCopier.copyBeanProperties(type,enhanced,original);
if(lazyLoader.size()>0){
returnnewJavassistSerialStateHolder(original,lazyLoader.getProperties(),objectFactory,constructorArgTypes,constructorArgs);
}else{
returnoriginal;
}
}else{
//延迟加载数量大于0
if(lazyLoader.size()>0&&!FINALIZE_METHOD.equals(methodName)){
//aggressive一次加载性所有需要要延迟加载属性或者包含触发延迟加载方法
if(aggressive||lazyLoadTriggerMethods.contains(methodName)){
log.debug("==>lazelodtriggermethod:"+methodName+",proxymethod:"+methodProxy.getName()+"class:"+enhanced.getClass());
//一次全部加载
lazyLoader.loadAll();
}elseif(PropertyNamer.isSetter(methodName)){
//判断是否为set方法,set方法不需要延迟加载
finalStringproperty=PropertyNamer.methodToProperty(methodName);
lazyLoader.remove(property);
}elseif(PropertyNamer.isGetter(methodName)){
finalStringproperty=PropertyNamer.methodToProperty(methodName);
if(lazyLoader.hasLoader(property)){
//延迟加载单个属性
lazyLoader.load(property);
log.debug("loadone:"+methodName);
}
}
}
}
}
returnmethodProxy.invoke(enhanced,args);
}catch(Throwablet){
throwExceptionUtil.unwrapThrowable(t);
}
}
}
load方法
/**
*执行懒加载查询,获取数据并且set到userObject中返回
*@paramuserObject
*@throwsSQLException
*/
publicvoidload(finalObjectuserObject)throwsSQLException{
//合法性校验
if(this.metaResultObject==null||this.resultLoader==null){
if(this.mappedParameter==null){
thrownewExecutorException("Property["+this.property+"]cannotbeloadedbecause"
+"requiredparameterofmappedstatement["
+this.mappedStatement+"]isnotserializable.");
}
//获取mappedstatement并且校验
finalConfigurationconfig=this.getConfiguration();
finalMappedStatementms=config.getMappedStatement(this.mappedStatement);
if(ms==null){
thrownewExecutorException("Cannotlazyloadproperty["+this.property
+"]ofdeserializedobject["+userObject.getClass()
+"]becauseconfigurationdoesnotcontainstatement["
+this.mappedStatement+"]");
}
//使用userObject构建metaobject,并且重新构建resultloader对象
this.metaResultObject=config.newMetaObject(userObject);
this.resultLoader=newResultLoader(config,newClosedExecutor(),ms,this.mappedParameter,
metaResultObject.getSetterType(this.property),null,null);
}
/*Weareusinganewexecutorbecausewemaybe(andlikelyare)onanewthread
*andexecutorsaren'tthreadsafe.(Isthissufficient?)
*
*Abetterapproachwouldbemakingexecutorsthreadsafe.*/
if(this.serializationCheck==null){
finalResultLoaderold=this.resultLoader;
this.resultLoader=newResultLoader(old.configuration,newClosedExecutor(),old.mappedStatement,
old.parameterObject,old.targetType,old.cacheKey,old.boundSql);
}
//获取数据库查询结果并且set到结果对象返回
this.metaResultObject.setValue(property,this.resultLoader.loadResult());
}
参考地址:
https://www.cnblogs.com/qixidi/p/10251126.html
https://blog.csdn.net/mingtian625/article/details/47358003
到此这篇关于Mybatis懒加载的实现的文章就介绍到这了,更多相关Mybatis懒加载内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!