【保姆级】lookup-method标签实践与分析

有目标就不怕路远。年轻人.无论你现在身在何方.重要的是你将要向何处去。只有明确的目标才能助你成功。没有目标的航船.任何方向的风对他来说都是逆风。因此,再遥远的旅程,只要有目标.就不怕路远。没有目标,哪来的劲头?一车尔尼雷夫斯基

导读:本篇文章讲解 【保姆级】lookup-method标签实践与分析,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

【Spring源码系列- IOC】

1

【Spring源码】0.安装Gradle环境

2

【Spring源码】1.下载与编译_pom relocation to an other version number is not f

3

【Spring源码】2.试个水先~Debug找到传说中的三级缓存(图解向,堆图预警)

4

【Spring源码】3. xml文件如何转换成BeanDefinition(主要涉及prepareRefresh()+ obtainFreshBeanFactory()两个函数,图解向,堆图预警)_spring xml转bean

5

【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)

6

【Spring源码】5.spring的bean工厂准备工作(prepareBeanFactory(beanFactory)

7

【Spring源码】6. Spring扩展自定义属性编辑器保姆级教程

8

【Spring源码】7. 如何添加自定义的BeanFactoryPostProcessor

9

【Spring源码】8. 捋下invokeBeanFactoryPostProcessors()主要处理流程

10

【Spring源码】9. 超级重要的ConfigurationClassPostProcessor

11

【Spring源码】10. 递归调用的processConfigurationClass()方法

12

【Spring源码】11. 我是注解类不?checkConfigurationClassCandidate()注解类判断方法详解

13

【Spring源码】12. 注册bean处理器registerBeanPostProcessors()

14

【Spring源码】13. 国际化处理initMessageSource()源码解析

【补充内容】【保姆级】SpringBoot项目中的i18n国际化

15

【Spring源码】14. 消息多播器(观察者模式)

【补充内容】【保姆级示例向】观察者模式

16

【Spring源码】15. Bean的创建过程(1.概述篇)

17

【Spring源码】16. Bean的创建过程(2)

18

【Spring源码】17.创建Bean这篇认真的@(・●・)@

【补充内容】

【保姆级·创建对象】如何通过Supplier创建对象

【保姆级·创建对象】如何通过factory-method创建对象

【保姆级·创建对象】如何利用resolveBeforeInstantiation()在预处理阶段返回一个Bean的实例对象

19

【Spring源码】18. factory-method创建对象关键函数详解:instantiateUsingFactoryMethod()

20

【Spring源码】19. 没合适的构造器?找determineCandidateConstructors()!

21

【Spring源码】20. MergedBeanDefinitionPostProcessor修改/合并bean定义

【补充内容】

【保姆级】@PostConstruct & @PreDestroy使用示例

【Spring源码】AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition()详解

【Spring源码】CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition()详解

22

【Spring源码】21. 初探循环依赖

【补充内容】

【保姆级】手把手Debug循环依赖的整体流程

【实践向】当移除了三级缓存……

【分析向】没有三级缓存会导致什么?

【Spring源码】插播一个创建代理对象的wrapIfNecessary()方法

23

【Spring源码】22. 属性填充populateBean()详解

【补充内容】

【Spring源码】自动注入·名称:autowireByName()详解

【Spring源码】自动注入·类型:autowireByType()详解

【Spring源码】属性值的解析与赋值:populateBean().applyPropertyValues()

【保姆级】超超超简单的自定义注解实现@Autowired同款功能

24

【Spring源码】23. 执行初始化逻辑:initializeBean()

本文目录

🌰

文件结构

​创建实体类

创建配置文件

新建Spring配置文件

创建测试类

测试结果

​测试分析

获取一个类的不同实例

xml配置文件

测试结果

​测试分析


一句话:这个注解是在单例中引用原型使用的

详细点说:Spring中默认的对象都是单例的(而且Spring会在一级缓存中保存该对象以便下次直接获取),如果是原型作用域,每次会创建一个新的对象。如果在单例模式的bean下引用一个原型模式的bean,此时就需要引用lookup-method标签来解决此类问题。 个人理解:由于当调用getBean()方法时,Spring会先在容器中查找有没有这个类,或者这个类的子类,通常情况下,Spring在查找的时候,如果没有匹配或者匹配到多个类都会报错,然而我们又想在一个程序中实现如下两个功能:

  • 分别获取这个父类的两个不同的子类的实例

  • 每次获取到的都是同一个类的不同实例

而lookup-method这个标签就是解决这些问题的

本文就是这两种情况的栗子🌰,感兴趣的同学可以跟着一步一步操作,绝对保姆级教程(不愧是俺(˶‾᷄ ⁻̫ ‾᷅˵))

🌰

获取同一父类的不同子类

文件结构

这个示例一共需要新建6个文件

【保姆级】lookup-method标签实践与分析

​创建实体类

有4个实体类(一个父类+两个子类+一个操作类)

Animal.java(父类)

【保姆级】lookup-method标签实践与分析

package com.aqin.custom.MethodOverride.lookup;

/**
 * @Description
 * @Author aqin1012 AQin.
 * @Date 2022/8/22 9:28 AM
 * @Version 1.0
 */
public class Animal {
   public Animal() {
      System.out.println("吃点啥嘞?");
   }
}

Cat.java

【保姆级】lookup-method标签实践与分析

package com.aqin.custom.MethodOverride.lookup;

/**
 * @Description
 * @Author aqin1012 AQin.
 * @Date 2022/8/22 10:01 AM
 * @Version 1.0
 */
public class Cat extends Animal{
   public Cat() {
      System.out.println("吃(_ _).。oO……猫粮");
   }
}

Dog.java

【保姆级】lookup-method标签实践与分析

package com.aqin.custom.MethodOverride.lookup;

/**
 * @Description
 * @Author aqin1012 AQin.
 * @Date 2022/8/22 9:29 AM
 * @Version 1.0
 */
public class Dog extends Animal{
   public Dog() {
      System.out.println("吃(*≧ω≦)……狗粮");
   }
}

AnimalAction.java

【保姆级】lookup-method标签实践与分析

package com.aqin.custom.MethodOverride.lookup;

/**
 * @Description
 * @Author aqin1012 AQin.
 * @Date 2022/8/22 10:25 AM
 * @Version 1.0
 */
public abstract class AnimalAction {
   /**
    * 获取执行该动作的动物
    *
    * @return
    */
   public abstract Animal getAnimal();
}

创建配置文件

【保姆级】lookup-method标签实践与分析

新建Spring配置文件

【保姆级】lookup-method标签实践与分析

​添加如下bean定义:

<bean id="dog" class="com.aqin.custom.MethodOverride.lookup.Dog"></bean>
<bean id="cat" class="com.aqin.custom.MethodOverride.lookup.Cat"></bean>

<bean id="animalAction_A" class="com.aqin.custom.MethodOverride.lookup.AnimalAction">
   <lookup-method name="getAnimal" bean="dog"></lookup-method>
</bean>

<bean id="animalAction_B" class="com.aqin.custom.MethodOverride.lookup.AnimalAction">
   <lookup-method name="getAnimal" bean="cat"></lookup-method>
</bean>

创建测试类

【保姆级】lookup-method标签实践与分析

package com.aqin.custom.MethodOverride.test;

import com.aqin.custom.MethodOverride.lookup.AnimalAction;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Description
 * @Author aqin1012 AQin.
 * @Date 2022/8/22 10:29 AM
 * @Version 1.0
 */
public class TestMethodOverride {
   public static void main(String[] args) {
      ApplicationContext applicationContext = new ClassPathXmlApplicationContext("MethodOverride.xml");
      AnimalAction animalActionA = (AnimalAction) applicationContext.getBean("animalAction_A");
      animalActionA.getAnimal();
      AnimalAction animalActionB = (AnimalAction) applicationContext.getBean("animalAction_B");
      animalActionB.getAnimal();
   }
}

测试结果

【保姆级】lookup-method标签实践与分析

​测试分析

先在下图位置打个断点

【保姆级】lookup-method标签实践与分析

​选择debug方式执行

【保姆级】lookup-method标签实践与分析

不断下一步,直到我们在配置类中配置的4个Bean都能在this对象中的singletonObjects中找到的时候,我们来查看使用了lookup-method标签的那两个Bean,可以看到这两个对象都是cglib的代理对象

【保姆级】lookup-method标签实践与分析

​当调用到getAnimal()方法时,会跳转到CglibSubclassingInstantiationStrategy中的intercept()方法中

【保姆级】lookup-method标签实践与分析

这里的lo是animalAction_A,可以看到lo中的beanName跟xml配置文件中animalAction_A的<lookup-method name=”getAnimal” bean=”dog”></lookup-method>标签中的bean=”dog”是相对应的(animalAction_B类似)

【保姆级】lookup-method标签实践与分析

获取一个类的不同实例

文件就用上面的结构就可以了,需要修改下测试类和xml配置文件

测试类做如下修改

【保姆级】lookup-method标签实践与分析

public class TestMethodOverride {
   public static void main(String[] args) {
      ApplicationContext applicationContext = new ClassPathXmlApplicationContext("MethodOverride.xml");
      AnimalAction animalActionB = (AnimalAction) applicationContext.getBean("animalAction_B");
      animalActionB.getAnimal();
      AnimalAction animalActionB_2 = (AnimalAction) applicationContext.getBean("animalAction_B");
      animalActionB_2.getAnimal();
   }
}

xml配置文件

【保姆级】lookup-method标签实践与分析

<bean id="dog" class="com.aqin.custom.MethodOverride.lookup.Dog" scope="prototype"></bean>
<bean id="cat" class="com.aqin.custom.MethodOverride.lookup.Cat" scope="prototype"></bean>

测试结果

【保姆级】lookup-method标签实践与分析

​测试分析

此时this对象中的singletonObjects中就只有animalAction_A和animalAction_B两个了(因为Cat和Dog都的scope设置成了prototype(原型))

【保姆级】lookup-method标签实践与分析

​可以看到,两次获取的Cat一个是Cat@1730,一个是Cat@1790,并不是同一个对象,实现了在单例中引用原型(单例的bean会被Spring放在一级缓存中保存,以便下次直接获取,所以每次获取到的都是同一个实例)

【保姆级】lookup-method标签实践与分析

【保姆级】lookup-method标签实践与分析

返回的实际上是一个动态代理生成的对象

【保姆级】lookup-method标签实践与分析

撒花(。・ω・。)ノ🎉🎉🎉

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/135387.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!