久久r热视频,国产午夜精品一区二区三区视频,亚洲精品自拍偷拍,欧美日韩精品二区

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

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

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

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

一、一個簡單的小例子

代碼如下:

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

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

二、源碼解讀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,懶加載,此時spring會根據(jù)具體類型搞個cglib代理類Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);if (result == null) {result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);}return result;}}

很明顯要執(zhí)行g(shù)etLazyResolutionProxyIfNecessary方法,如果加了@Lazy注解,最終會執(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());}

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

2. 使用邏輯

本文示例代碼使用的是CGLIB代理,其實是類似的,因為注入的MyService是個CGLIB代理對象,那么在執(zhí)行方法的時候,就會調(diào)用CglibAopProxy#DynamicAdvisedInterceptor#intercept方法

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

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

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

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

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

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

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

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

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

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

總結(jié)

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

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

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

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 惠水县| 穆棱市| 杭州市| 喀喇沁旗| 南充市| 伽师县| 永德县| 天镇县| 武宁县| 新密市| 广西| 平阳县| 方正县| 福建省| 锡林郭勒盟| 增城市| 方正县| 图们市| 泸溪县| 青田县| 德州市| 滦平县| 稷山县| 明溪县| 岳普湖县| 会泽县| 驻马店市| 宁津县| 松溪县| 东城区| 珠海市| 恭城| 乌兰察布市| 烟台市| 大安市| 元阳县| 奉贤区| 深州市| 延安市| 武冈市| 策勒县|