电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

spring @Lazy延遲注入的邏輯實(shí)現(xiàn)

瀏覽:2日期:2023-06-27 10:20:45
目錄前言一、一個(gè)簡單的小例子二、源碼解讀1. 注入2. 使用邏輯總結(jié)前言

有時(shí)候我們會(huì)在屬性注入的時(shí)候添加@Lazy注解實(shí)現(xiàn)延遲注入,今天咱們通過閱讀源碼來分析下原因

一、一個(gè)簡單的小例子

代碼如下:

@Servicepublic class NormalService1 {@Autowired@Lazyprivate MyService myService;public void doSomething() {myService.getName();}}

作用是為了進(jìn)行延遲加載,在NormalService1進(jìn)行屬性注入的時(shí)候,如果MyService還沒有生成bean也不用擔(dān)心,會(huì)注入一個(gè)代理,但是在實(shí)際運(yùn)行的時(shí)候,會(huì)獲取Spring容器中實(shí)際的MyService,在某些情況下,因?yàn)閟pring生命周期的原因,這個(gè)注解有大用。

二、源碼解讀1. 注入

代碼如下(DefaultListableBeanFactory#resolveDependency):

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());if (Optional.class == descriptor.getDependencyType()) {return createOptionalDependency(descriptor, requestingBeanName);}else if (ObjectFactory.class == descriptor.getDependencyType() ||ObjectProvider.class == descriptor.getDependencyType()) {return new DependencyObjectProvider(descriptor, requestingBeanName);}else if (javaxInjectProviderClass == descriptor.getDependencyType()) {return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);}else {//如果注入屬性添加了@Lazy,懶加載,此時(shí)spring會(huì)根據(jù)具體類型搞個(gè)cglib代理類Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);if (result == null) {result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);}return result;}}

很明顯要執(zhí)行g(shù)etLazyResolutionProxyIfNecessary方法,如果加了@Lazy注解,最終會(huì)執(zhí)行buildLazyResolutionProxy方法

protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final @Nullable String beanName) {Assert.state(getBeanFactory() instanceof DefaultListableBeanFactory,'BeanFactory needs to be a DefaultListableBeanFactory');final DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) getBeanFactory();TargetSource ts = new TargetSource() {@Overridepublic Class<?> getTargetClass() {return descriptor.getDependencyType();}@Overridepublic boolean isStatic() {return false;}@Overridepublic Object getTarget() {Object target = beanFactory.doResolveDependency(descriptor, beanName, null, null);/**something valid**/return target;}@Overridepublic void releaseTarget(Object target) {}};ProxyFactory pf = new ProxyFactory();pf.setTargetSource(ts);Class<?> dependencyType = descriptor.getDependencyType();if (dependencyType.isInterface()) {pf.addInterface(dependencyType);}return pf.getProxy(beanFactory.getBeanClassLoader());}

可以看到上面這段代碼,其實(shí)就是生成了一個(gè)TargetSource,然后再生成了一個(gè)代理(CGLIB或者JDK),然后作為MyService對象注入給了NormalService1。那么所謂的執(zhí)行的過程中才進(jìn)行獲取真正的MyService對象是什么意思呢?

2. 使用邏輯

本文示例代碼使用的是CGLIB代理,其實(shí)是類似的,因?yàn)樽⑷氲腗yService是個(gè)CGLIB代理對象,那么在執(zhí)行方法的時(shí)候,就會(huì)調(diào)用CglibAopProxy#DynamicAdvisedInterceptor#intercept方法

spring @Lazy延遲注入的邏輯實(shí)現(xiàn)

那么此處其實(shí)調(diào)用的就是上面的

Object target = beanFactory.doResolveDependency(descriptor, beanName, null, null);

這個(gè)方法就不用認(rèn)真看了,主要功能就是從Spring容器中找到MyService。在之前講@Autowired原理和@Resource注入原理的時(shí)候解釋過了,不清楚的可以看專欄里其他文章。拿出來之后會(huì)發(fā)現(xiàn),咱們拿到的target對象還是一個(gè)CGLIB增加的對象

spring @Lazy延遲注入的邏輯實(shí)現(xiàn)

那么當(dāng)執(zhí)行方法邏輯時(shí)

spring @Lazy延遲注入的邏輯實(shí)現(xiàn)

由于target是CGLIB對象,會(huì)再次進(jìn)入到CglibAopProxy#DynamicAdvisedInterceptor#intercept方法。此時(shí)拿到的target對象類型就不同了

spring @Lazy延遲注入的邏輯實(shí)現(xiàn)

是我們代理之前的target對象,此時(shí)再次進(jìn)行invoke的時(shí)候,就會(huì)進(jìn)行動(dòng)態(tài)代理的一般邏輯,先查找該方法匹配的所有advice,然后依次調(diào)用,最終調(diào)用target本身對于方法的執(zhí)行。

總結(jié)

所以可以發(fā)現(xiàn)其實(shí)@Lazy只不過是給spring的代理對象proxy再進(jìn)行了一次proxy,只不過沒有在注入的時(shí)候,就獲取到對象,而是借用了方法invoke時(shí)通過proxy的intercept方法getTarget,然后進(jìn)行方法調(diào)用,延遲了對象的注入。之后每次調(diào)用的時(shí)候都需要從Spring容器中獲取到原生的proxy對象。

spring @Lazy延遲注入的邏輯實(shí)現(xiàn)

到此這篇關(guān)于spring @Lazy延遲注入的邏輯實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)spring @Lazy延遲注入內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 可程式恒温恒湿试验箱|恒温恒湿箱|恒温恒湿试验箱|恒温恒湿老化试验箱|高低温试验箱价格报价-广东德瑞检测设备有限公司 | 郑州爱婴幼师学校_专业幼师培训_托育师培训_幼儿教育培训学校 | 电子巡更系统-巡检管理系统-智能巡检【金万码】 | 馋嘴餐饮网_餐饮加盟店火爆好项目_餐饮连锁品牌加盟指南创业平台 | 执业药师报名条件,考试时间,考试真题,报名入口—首页 | 柔性测斜仪_滑动测斜仪-广州杰芯科技有限公司 | 酒水灌装机-白酒灌装机-酒精果酒酱油醋灌装设备_青州惠联灌装机械 | 外贸资讯网 - 洞悉全球贸易,把握市场先机 | 南京试剂|化学试剂|分析试剂|实验试剂|cas号查询-专业60年试剂销售企业 | 大型果蔬切片机-水果冬瓜削皮机-洗菜机切菜机-肇庆市凤翔餐饮设备有限公司 | 圆窗水平仪|伊莉莎冈特elesa+ganter | 回转支承-转盘轴承-回转驱动生产厂家-洛阳隆达轴承有限公司 | 柴油机_柴油发电机_厂家_品牌-江苏卡得城仕发动机有限公司 | 东莞压铸厂_精密压铸_锌合金压铸_铝合金压铸_压铸件加工_东莞祥宇金属制品 | 仿古瓦,仿古金属瓦,铝瓦,铜瓦,铝合金瓦-西安东申景观艺术工程有限公司 | 多功能真空滤油机_润滑油全自动滤油机_高效真空滤油机价格-重庆润华通驰 | 韦伯电梯有限公司| 厚壁钢管-厚壁无缝钢管-小口径厚壁钢管-大口径厚壁钢管 - 聊城宽达钢管有限公司 | 珠海冷却塔降噪维修_冷却塔改造报价_凉水塔风机维修厂家- 广东康明节能空调有限公司 | 深圳高新投三江工业消防解决方案提供厂家_服务商_园区智慧消防_储能消防解决方案服务商_高新投三江 | 冰晶石|碱性嫩黄闪蒸干燥机-有机垃圾烘干设备-草酸钙盘式干燥机-常州市宝康干燥 | 恒温恒湿箱(药品/保健品/食品/半导体/细菌)-兰贝石(北京)科技有限公司 | 非甲烷总烃分析仪|环控百科 | 大巴租车平台承接包车,通勤班车,巴士租赁业务 - 鸿鸣巴士 | 流量卡中心-流量卡套餐查询系统_移动电信联通流量卡套餐大全 | LED灯杆屏_LED广告机_户外LED广告机_智慧灯杆_智慧路灯-太龙智显科技(深圳)有限公司 | 全自动端子机|刺破式端子压接机|全自动双头沾锡机|全自动插胶壳端子机-东莞市傅氏兄弟机械设备有限公司 | 细胞染色-流式双标-试剂盒免费代做-上海研谨生物科技有限公司 | 电缆接头_防水接头_电缆防水接头 - 乐清市新豪电气有限公司 | 浙江华锤电器有限公司_地磅称重设备_防作弊地磅_浙江地磅售后维修_无人值守扫码过磅系统_浙江源头地磅厂家_浙江工厂直营地磅 | 集菌仪厂家_全封闭_封闭式_智能智能集菌仪厂家-上海郓曹 | 彼得逊采泥器-定深式采泥器-电动土壤采样器-土壤样品风干机-常州索奥仪器制造有限公司 | 交通气象站_能见度检测仪_路面状况监测站- 天合环境科技 | 真空乳化机-灌装封尾机-首页-温州精灌 | 制氮设备-变压吸附制氮设备-制氧设备-杭州聚贤气体设备制造有限公司 | 衡阳耐适防护科技有限公司——威仕盾焊接防护用品官网/焊工手套/焊接防护服/皮革防护手套 | 提升海外网站流量,增加国外网站访客UV,定制海外IP-访客王 | 吸污车_吸粪车_抽粪车_电动三轮吸粪车_真空吸污车_高压清洗吸污车-远大汽车制造有限公司 | 激光内雕_led玻璃_发光玻璃_内雕玻璃_导光玻璃-石家庄明晨三维科技有限公司 激光内雕-内雕玻璃-发光玻璃 | 珠海网站建设_响应网站建设_珠海建站公司_珠海网站设计与制作_珠海网讯互联 | 洁净实验室工程-成都手术室净化-无尘车间装修-四川华锐净化公司-洁净室专业厂家 |