方法注入可分为两种
在Spring容器中,单例模式的bean只会被创建一次,然后容器会缓存该单例bean的实例,等到第二次获取时,可以直接返回该bean的实例,而无需重新创建;原型模式的bean则是每次都会创建一个全新的bean,Spring容器并不会缓存该bean的实例以供下次使用。那么如果现在有一个单例模式的bean引用了一个原型模式的bean呢?我们不希望被引用的原型模式bean被缓存,那么这个时候就需要用到lookup-method注入。
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; } }
<?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>
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 ========测试方法结束=======
从运行结果可以看到
主要作用就是替换方法体及其返回值,其实现也比较简单
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; } }
<!-- ====================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==================== -->
/** * 测试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在实际开发中并不多见,但是应该有所了解,其底层涉及到的动态代理等机制,还是值得我们去深入了解的,具体的实现我们会在接下来的章节中进行分析。
————————————————
原文链接:https://blog.csdn.net/lyc_liyanchao/java/article/details/82432993
Spring lookup-method注入和replace-method注入
原文:https://www.cnblogs.com/w2116o2115/p/12706232.html