Spring5源码(7)-lookup-method和replace-method注入

简介: Spring5源码(7)-lookup-method和replace-method注入


Spring的方法注入可分为两种

  • 查找方法注入:用于注入方法返回结果,也就是说能通过配置方式替换方法返回结果。即我们通常所说的lookup-method注入。
  • 替换方法注入:可以实现方法主体或返回结果的替换,即我们通常所说的replaced-method注入。
1. lookup-method注入

单例模式的bean只会被创建一次,IoC容器会缓存该bean实例以供下次使用;原型模式的bean每次都会创建一个全新的bean,IoC容器不会缓存该bean的实例。那么如果现在有一个单例模式的bean引用了一个原型模式的bean呢?如果无特殊处理,则被引用的原型模式的bean也会被缓存,这就违背了原型模式的初衷,这时使用lookup-method注入可以解决该问题。

  • bean

package com.lyc.cn.v2.day01.method.lookupMethod;
/**
 * @author: LiYanChao
 * @create: 2018-09-05 15:10
 */
public abstract class Car {
    //用于lookup-method注入
    public abstract Taxi createTaxi();
    private Taxi taxi;
    public Taxi getTaxi() {
        return taxi;
    }
    //setter注入
    public void setTaxi(Taxi taxi) {
        this.taxi = taxi;
    }
}

package com.lyc.cn.v2.day01.method.lookupMethod;
/**
 * @author: LiYanChao
 * @create: 2018-09-05 15:10
 */
public class Taxi {
    public void say() {
        System.out.println("I am a Taxi...");
    }
}
  • xml

<!-- ====================lookup-method属性注入==================== -->
<bean id="car" class="com.lyc.cn.v2.day01.method.lookupMethod.Car">
    <!--注意:下面这句配置和lookup-method注入没有关系,我们只是为了出于演示和说明配置该bean-->
    <property name="taxi" ref="taxi"/>
    <!--lookup-method注入-->
    <lookup-method name="createTaxi" bean="taxi"/>
</bean>
<bean id="taxi" class="com.lyc.cn.v2.day01.method.lookupMethod.Taxi" scope="prototype"/>
<!-- ====================replace-method属性注入==================== -->
<bean id="dogReplaceMethod" class="com.lyc.cn.v2.day01.method.replaceMethod.ReplaceDog"/>
<bean id="originalDogReplaceMethod" class="com.lyc.cn.v2.day01.method.replaceMethod.OriginalDog">
    <replaced-method name="sayHello" replacer="dogReplaceMethod">
        <arg-type match="java.lang.String"></arg-type>
    </replaced-method>
</bean>
  • 测试

@Test
public void test8() {
    // 测试lookup-method注入
    Car car1 = xmlBeanFactory.getBean("car", Car.class);
    Car car2 = xmlBeanFactory.getBean("car", Car.class);
    System.out.println("Car:singleton,所以animal1==animal2应该为" + (car1 == car2));
    Taxi dog1 = car1.getTaxi();
    Taxi dog2 = car2.getTaxi();
    System.out.println("Taxi:prototype,Car:singleton,未使用lookup-method注入所以dog1==dog2应该为" + (dog1 == dog2));
    //注意:这里是通过createDog()方法获取
    Taxi taxi3 = car1.createTaxi();
    Taxi taxi4 = car2.createTaxi();
    System.out.println("Taxi:prototype,Car:singleton,使用了lookup-method注入所以dog3==dog4应该为" + (taxi3 == taxi4));
}
  • 结果

========测试方法开始=======
Car:singleton,所以animal1==animal2应该为true
Taxi:prototype,Car:singleton,未使用lookup-method注入所以dog1==dog2应该为true
Taxi:prototype,Car:singleton,使用了lookup-method注入所以dog3==dog4应该为false
========测试方法结束=======
  • 分析
    未使用lookup-method注入时,通过Car的实例获取的Taxi实例是被缓存的(配置文件中Taxi的scope="prototype");而使用了lookup-method注入时,通过Car的实例获取的Taxi实例则是每次都是新建的,不是被缓存的,这也就达到了我们的目的。
2. replaced-method注入

主要作用就是替换方法体及其返回值,其实现也比较简单

  • bean

package com.lyc.cn.v2.day01.method.replaceMethod;
/**
 * @author: LiYanChao
 * @create: 2018-09-06 00:01
 */
public class OriginalDog {
    public void sayHello() {
        System.out.println("Hello,I am a black dog...");
    }
    public void sayHello(String name) {
        System.out.println("Hello,I am a black dog, my name is " + name);
    }
}

package com.lyc.cn.v2.day01.method.replaceMethod;
import org.springframework.beans.factory.support.MethodReplacer;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
 * @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...");
        Arrays.stream(args).forEach(str -> System.out.println("参数:" + str));
        return obj;
    }
}

replace-method注入需实现MethodReplacer接口,并重写reimplement方法。

  • xml

<!-- ====================replace-method属性注入==================== -->
<bean id="dogReplaceMethod" class="com.lyc.cn.v2.day01.method.replaceMethod.ReplaceDog"/>
<bean id="originalDogReplaceMethod" class="com.lyc.cn.v2.day01.method.replaceMethod.OriginalDog">
    <replaced-method name="sayHello" replacer="dogReplaceMethod">
        <arg-type match="java.lang.String"></arg-type>
    </replaced-method>
</bean>
  • 测试

@Test
public void test9() {
    //测试replace-method注入
    OriginalDog originalDog = xmlBeanFactory.getBean("originalDogReplaceMethod", OriginalDog.class);
    originalDog.sayHello("输出结果已经被替换了。。。");
}
  • 结果

========测试方法开始=======
Hello, I am a white dog...
参数:输出结果已经被替换了。。。
========测试方法结束=======
  • 分析
    OriginalDog类的sayHello方法输出的是Hello,I am a black dog, my name is xxx,但是通过replace-method注入,成功的将其替换成reimplement方法。

本节的内容基于配置,只要了解如何配置,就可以正常使用了,不在做过多的分析。




目录
相关文章
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
71 2
|
1月前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
2月前
|
Java Spring
在使用Spring的`@Value`注解注入属性值时,有一些特殊字符需要注意
【10月更文挑战第9天】在使用Spring的`@Value`注解注入属性值时,需注意一些特殊字符的正确处理方法,包括空格、引号、反斜杠、新行、制表符、逗号、大括号、$、百分号及其他特殊字符。通过适当包裹或转义,确保这些字符能被正确解析和注入。
128 3
|
2月前
|
Java 测试技术 程序员
为什么Spring不推荐@Autowired用于字段注入?
作为Java程序员,Spring框架在日常开发中使用频繁,其依赖注入机制带来了极大的便利。然而,尽管@Autowired注解简化了依赖注入,Spring官方却不推荐在字段上使用它。本文将探讨字段注入的现状及其存在的问题,如难以进行单元测试、违反单一职责原则及易引发NPE等,并介绍为何Spring推荐构造器注入,包括增强代码可读性和维护性、方便单元测试以及避免NPE等问题。通过示例代码展示如何将字段注入重构为构造器注入,提高代码质量。
107 1
|
10天前
|
Java Spring
一键注入 Spring 成员变量,顺序编程
介绍了一款针对Spring框架开发的插件,旨在解决开发中频繁滚动查找成员变量注入位置的问题。通过一键操作(如Ctrl+1),该插件可自动在类顶部添加`@Autowired`注解及其成员变量声明,同时保持光标位置不变,有效提升开发效率和代码编写流畅度。适用于IntelliJ IDEA 2023及以上版本。
一键注入 Spring 成员变量,顺序编程
|
16天前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
38 2
|
1月前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
63 9
|
2月前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
145 5
|
2月前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
2月前
|
设计模式 JavaScript Java
Spring 事件监听机制源码
Spring 提供了事件发布订阅机制,广泛应用于项目中。本文介绍了如何通过自定义事件类、订阅类和发布类实现这一机制,并展示了如何监听 SpringBoot 启动过程中的多个事件(如 `ApplicationStartingEvent`、`ApplicationEnvironmentPreparedEvent` 等)。通过掌握这些事件,可以更好地理解 SpringBoot 的启动流程。示例代码展示了从事件发布到接收的完整过程。