当前位置: 首页 > news >正文

NHibernate实现延迟加载的主要结构:


BuildSessionFactory的时候:
1. 根据proxyfactory.factory_class的配置创建IProxyFactoryFactory对象
2. 如果use_proxy_validator配置为true(默认为true),加载实体映射元数据之后,对需要代理的实体使用IProxyFactoryFactory的ProxyValidator进行验证(例如要求实体有默认构造器、方法属性必须为virtual类型等)
3. 为需要代理的实体类型创建IProxyFactory,并调用IProxyFactory对象的PostInstantiate方法
对每一个需要代理的实体类型都会创建一个IProxyFactory对象并缓存,创建代理对象则通过IProxyFactory的GetProxy方法完成
AbstractProxyFactory主要是实现PostInstantiate方法,这个方法主要是将创建代理对象所需的信息记录下来,例如EntityName(字符串的实体类名)、PersistentClass(代理对象的System.Type)、Interfaces(代理对象需要额外实现的接口,例如INHibernateProxy),其他几个记录的属性则为单主键和组合主键id的get、set方法
ProxyFactory则主要实现GetProxy方法,使用Castle或者LinFu等动态代理库以及上述信息创建代理对象

创建代理对象:
IProxyFactory.GetProxy方法完成
1. 创建一个LazyInitializer对象。LazyInitializer实现了各个动态代理类库的拦截器接口
2. 通过Castle、LinFu、Spring等动态代理库创建class proxy或者interface proxy的代理对象
创建代理对象时INHibernateProxy作为一个mixin的接口,NHibernate内部用这个接口来区分代理对象和真实对象。对这个接口的方法调用则在拦截器中处理

延迟加载:
创建代理对象时,均使用NHibernate.ByteCode.LinFu或者NHibernate.ByteCode.Castle中的LazyInitializer类作为拦截器,因此对代理对象的方法调用都在LazyInitializer中拦截处理
ILazyInitializer接口主要用于延迟加载的相关处理
首先,对代理对象某些方法的调用不会触发延迟加载行为,比如读取主键的值、组合类型属性的主键值、没有override的情况下调用Object基类的一些方法以及Dispose方法等,这些逻辑在BasicLazyInitializer的Invoke方法中处理
当调用代理对象的其他方法时,触发延迟加载行为。加载处理在AbstractLazyInitializer的Initialize方法中完成,加载实体所需要的信息(主要有session、id、实体的类型)在创建LazyInitializer对象时均已经提供,加载过程仍然使用一级缓存、二级缓存、数据库这样一个加载顺序

加载的实体对象与代理对象是两个独立的对象,NHibernate并没有将加载后的实体属性值设置到代理对象上,估计一是考虑到有interface proxy存在的情况,另外实际加载过程是比较独立的,他会重新创建一个真实的实体对象,会放入一级、二级缓存中,还有一点,这种处理方式NHibernate以及client都可以通过代理对象来得到加载后的真实对象。真实的实体对象保存在AbstractLazyInitializer的Target属性中,完成加载以后,拦截器中通过反射来调用target对象的方法

下面代码示例怎么由代理对象得到真实对象(非NHibernate官方公布的方法,慎用):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

ISessionFactory sf =newConfiguration().Configure().BuildSessionFactory();

using(ISession session = sf.OpenSession())

{

//仅创建代理对象,没有实际加载

MyUser proxy = session.Load<MyUser>(11);

Console.WriteLine(proxy.GetType().FullName);

//因为override了ToString方法,因此下面这个调用将触发加载行为

Console.WriteLine(proxy.ToString());

//获取真实对象

NHibernate.Proxy.INHibernateProxy nhProxy = proxyasINHibernateProxy;

MyUser real = nhProxy.HibernateLazyInitializer.GetImplementation()asMyUser;

Console.WriteLine(real.GetType().FullName);

Console.WriteLine(real.ToString());

}

sf.Close();

Console.ReadKey();

下面是运行结果:

分类: NHibernate

http://www.jsqmd.com/news/1132478/

相关文章:

  • 湿地生态好不好,不能只看绿不绿
  • 依赖注入与对象间关系
  • MLS点云道路标线自动化提取:基于PCL与OpenCV实现95%+准确率(附代码)
  • 【学习记录】Week14(二):沙箱机制深度剖析与进阶 ORW 绕过体系
  • 从零学习Kafka:调优
  • # TDengine TMQ 最佳实践 — 可靠消费、容错与监控
  • Node.js-Phase 1 学习总结:CLI 文件管理系统
  • 3分钟极速指南:用Python工具一键获取国家中小学智慧教育平台电子课本
  • 一个独立开发者的审计日志平台
  • Linux 系统中定位与设置 JAVA_HOME 目录
  • MNIST 数据集 3 种主流框架加载对比:PyTorch vs TensorFlow vs Hugging Face Datasets
  • Educator头歌答案分享:数据预处理与特征工程在线实验闯关
  • Pot Desktop:5大核心功能解密,3分钟掌握跨平台翻译神器
  • Java面试突击指南!1个月拿下Java高级开发岗!AI大模型简历必备/面试必备!
  • Agentic RAG 方案深度解析:从概念到落地
  • 如何在Linux上流畅运行Windows游戏:DXVK终极配置指南
  • Fastboot Enhance:Windows平台一站式Android刷机工具箱,告别命令行复杂操作
  • Markdown锚点跳转失败的解决办法
  • Jetson Nano Super + Ubuntu 22.04 + ROS2 Humble:MID-360、FAST-LIO 与 EGO-Planner 实时建图部署记录
  • pytest-xdist分布式测试:加速APP自动化测试的架构与实战
  • 互联网大厂 Java 面试实录:谢飞机的三轮攻防战
  • 前后端分离爱心商城系统系统|SpringBoot+Vue+MyBatis+MySQL完整源码+部署教程
  • 从零搭建一个单节点 K8S 可观测实验室(一):从 Ubuntu 24.04 开始
  • HarmonyOS 小游戏《对战五子棋》开发第3篇-项目配置文件全解析
  • AI 已经改变工作方式,我们该怎么适应这场变化?
  • Codex 使用 Playwright Test Agents
  • 换种不同的方式调用WCF服务[提供源代码下载]
  • 3步解锁中医AI:如何让“仲景“大语言模型成为你的智能中医助手
  • 程序员的语言“艳遇史”(四) ——数学系师姐forth
  • 尽量减少对DOM的操作