【Spring源码系列- IOC】
本文目录
一句话:这个注解是在单例中引用原型使用的
详细点说:Spring中默认的对象都是单例的(而且Spring会在一级缓存中保存该对象以便下次直接获取),如果是原型作用域,每次会创建一个新的对象。如果在单例模式的bean下引用一个原型模式的bean,此时就需要引用lookup-method标签来解决此类问题。 个人理解:由于当调用getBean()方法时,Spring会先在容器中查找有没有这个类,或者这个类的子类,通常情况下,Spring在查找的时候,如果没有匹配或者匹配到多个类都会报错,然而我们又想在一个程序中实现如下两个功能:
-
分别获取这个父类的两个不同的子类的实例
-
每次获取到的都是同一个类的不同实例
而lookup-method这个标签就是解决这些问题的
本文就是这两种情况的栗子🌰,感兴趣的同学可以跟着一步一步操作,绝对保姆级教程(不愧是俺(˶‾᷄ ⁻̫ ‾᷅˵))
🌰
获取同一父类的不同子类
文件结构
这个示例一共需要新建6个文件
创建实体类
有4个实体类(一个父类+两个子类+一个操作类)
Animal.java(父类)
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
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
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
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();
}
创建配置文件
新建Spring配置文件
添加如下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>
创建测试类
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();
}
}
测试结果
测试分析
先在下图位置打个断点
选择debug方式执行
不断下一步,直到我们在配置类中配置的4个Bean都能在this对象中的singletonObjects中找到的时候,我们来查看使用了lookup-method标签的那两个Bean,可以看到这两个对象都是cglib的代理对象
当调用到getAnimal()方法时,会跳转到CglibSubclassingInstantiationStrategy中的intercept()方法中
这里的lo是animalAction_A,可以看到lo中的beanName跟xml配置文件中animalAction_A的<lookup-method name=”getAnimal” bean=”dog”></lookup-method>标签中的bean=”dog”是相对应的(animalAction_B类似)
获取一个类的不同实例
文件就用上面的结构就可以了,需要修改下测试类和xml配置文件
测试类做如下修改
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配置文件
<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>
测试结果
测试分析
此时this对象中的singletonObjects中就只有animalAction_A和animalAction_B两个了(因为Cat和Dog都的scope设置成了prototype(原型))
可以看到,两次获取的Cat一个是Cat@1730,一个是Cat@1790,并不是同一个对象,实现了在单例中引用原型(单例的bean会被Spring放在一级缓存中保存,以便下次直接获取,所以每次获取到的都是同一个实例)
返回的实际上是一个动态代理生成的对象
撒花(。・ω・。)ノ🎉🎉🎉
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/135387.html