14--Spring lookup-method注入和replace-method注入(二)

版权声明:如有转载,请标明出处,谢谢合作! 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方法注入传送:

猜你喜欢

转载自blog.csdn.net/lyc_liyanchao/article/details/82432993