版权声明:如有转载,请标明出处,谢谢合作! https://blog.csdn.net/lyc_liyanchao/article/details/82432993
上一小节介绍了Spring注入方式中的构造函数注入和Setter方法注入,接下来介绍另一种注入方法注入,方法注入可分为两种
- 查找方法注入:用于注入方法返回结果,也就是说能通过配置方式替换方法返回结果。即我们通常所说的lookup-method注入
- 替换方法注入:可以实现方法主体或返回结果的替换,即我们通常所说的replaced-method注入
1. lookup-method注入
在Spring容器中,单例模式的bean只会被创建一次,然后容器会缓存该单例bean的实例,等到第二次获取时,可以直接返回该bean的实例,而无需重新创建;原型模式的bean则是每次都会创建一个全新的bean,Spring容器并不会缓存该bean的实例以供下次使用。那么如果现在有一个单例模式的bean引用了一个原型模式的bean呢?我们不希望被引用的原型模式bean被缓存,那么这个时候就需要用到lookup-method注入。
- 新建Dog类和Animal抽象类
package com.lyc.cn.day05.lookupMethod;
/**
* @author: LiYanChao
* @create: 2018-09-05 15:10
*/
public class Dog {
public void say() {
System.out.println("I am a Dog...");
}
}
package com.lyc.cn.day05.lookupMethod;
/**
* @author: LiYanChao
* @create: 2018-09-05 15:10
*/
public abstract class Animal {
//用于lookup-method注入
public abstract Dog createDog();
private Dog dog;
public Dog getDog() {
return dog;
}
//setter注入
public void setDog(Dog dog) {
this.dog = dog;
}
}
- 新建day05.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- ====================lookup-method属性注入begin==================== -->
<bean id="animal" class="com.lyc.cn.day05.lookupMethod.Animal">
<!--注意:下面这句配置和lookup-method注入没有关系,我们只是为了出于演示和说明配置该bean-->
<property name="dog" ref="dog"/>
<!--lookup-method注入-->
<lookup-method name="createDog" bean="dog"/>
</bean>
<bean id="dog" class="com.lyc.cn.day05.lookupMethod.Dog" scope="prototype"/>
<!-- ====================lookup-method属性注入end==================== -->
</beans>
- 新建MyTest,添加测试用例
package com.lyc.cn.day05;
import com.lyc.cn.day05.lookupMethod.Animal;
import com.lyc.cn.day05.lookupMethod.Dog;
import com.lyc.cn.day05.replaceMethod.OriginalDog;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
/**
* @author: LiYanChao
* @create: 2018-09-08 01:01
*/
public class MyTest {
private XmlBeanFactory xmlBeanFactory;
@Before
public void initXmlBeanFactory() {
System.out.println("========测试方法开始=======\n");
xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("day05.xml"));
}
@After
public void after() {
System.out.println("\n========测试方法结束=======");
}
@Test
public void testLookUp() {
Animal animal1 = xmlBeanFactory.getBean("animal", Animal.class);
Animal animal2 = xmlBeanFactory.getBean("animal", Animal.class);
System.out.println("Animal:singleton,所以animal1==animal2应该为" + (animal1 == animal2));
Dog dog1 = animal1.getDog();
Dog dog2 = animal1.getDog();
System.out.println("Dog:prototype,Animal:singleton,未使用lookup-method注入所以dog1==dog2应该为" + (dog1 == dog2));
//注意:这里是通过createDog()方法获取
Dog dog3 = animal1.createDog();
Dog dog4 = animal1.createDog();
System.out.println("Dog:prototype,Animal:singleton,使用了lookup-method注入所以dog3==dog4应该为" + (dog3 == dog4));
}
}
- 运行测试用例
========测试方法开始=======
Animal:singleton,所以animal1==animal2应该为true
Dog:prototype,Animal:singleton,未使用lookup-method注入所以dog1==dog2应该为true
Dog:prototype,Animal:singleton,使用了lookup-method注入所以dog3==dog4应该为false
========测试方法结束=======
从运行结果可以看到
- Animal的作用域是singleton,所以虽然执行了两次getBean()方法,但是返回的是同一个Animal实例。
- Dog的作用域虽然是prototype,但是通过Setter方法注入的Dog返回的仍然是同一个对象,明显不符合prototype的概念。
- 通过lookup-method注入的Dog,每次返回的都是不同的对象,符合prototype的概念。
这里可能稍微有些绕,可以自己执行一下代码,比对一下结果,通过lookup-method就达到了在一种bean作用域下,使用其他作用域bean的效果。
1. replaced-method注入
主要作用就是替换方法体及其返回值,其实现也比较简单
- 新建OriginalDog和ReplaceDog(需实现MethodReplacer接口)
package com.lyc.cn.day05.replaceMethod;
/**
* @author: LiYanChao
* @create: 2018-09-06 00:01
*/
public class OriginalDog {
public void sayHello() {
System.out.println("Hello,I am a black dog...");
}
}
package com.lyc.cn.day05.replaceMethod;
import org.springframework.beans.factory.support.MethodReplacer;
import java.lang.reflect.Method;
/**
* @author: LiYanChao
* @create: 2018-09-06 00:02
*/
public class ReplaceDog implements MethodReplacer {
@Override
public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
System.out.println("Hello, I am a white dog...");
return obj;
}
}
- 修改day05.xml添加bean配置
<!-- ====================replace-method属性注入begin==================== -->
<bean id="replaceDog" class="com.lyc.cn.day05.replaceMethod.ReplaceDog"/>
<bean id="originalDog" class="com.lyc.cn.day05.replaceMethod.OriginalDog">
<replaced-method name="sayHello" replacer="replaceDog"/>
</bean>
<!-- ====================replace-method属性注入end==================== -->
- 修改MyTest类添加测试用例
/**
* 测试replace-method注入
*/
@Test
public void testReplace() {
OriginalDog originalDog = xmlBeanFactory.getBean("originalDog", OriginalDog.class);
originalDog.sayHello();
}
- 运行测试用例
========测试方法开始=======
Hello, I am a white dog...
========测试方法结束=======
查看结果,原本OriginalDog中的sayHell()输出已经被替换掉了。
关于Spring依赖注入的三种方式到这里就全部讲完了,lookup-method和replace-method在实际开发中并不多见,但是应该有所了解,其底层涉及到的动态代理等机制,还是值得我们去深入了解的,具体的实现我们会在接下来的章节中进行分析。
构造器和Setter方法注入传送: