首页 > 其他分享 >Spring 方法注入

Spring 方法注入

时间:2024-07-15 15:56:02浏览次数:9  
标签:Spring Object bean command Command 方法 public 注入

方法注入

        在大多数的应用场景下,多数的bean都是单例的。当这个单例的bean需要和另一个单例的或者非单例的bean协作使用的时候,开发者只需要配置依赖bean为这个bean的属性即可。 但是有时会因为bean具有不同的生命周期而产生问题。假设单例的bean A在每个方法调用中使用了非单例的bean B。容器只会创建bean A一次,而只有一个机会来配置属性。 那么容器就无法为每一次创建bean A时都提供新的bean B实例。

        一种解决方案就是放弃IoC,开发者可以通过实现ApplicationContextAware接口让bean A对ApplicationContext可见。 从而通过调用getBean("B")来在bean A 需要新的实例的时候来获取到新的B实例。参考下面例子。

// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;

// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class CommandManager implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public Object process(Map commandState) {
        // grab a new instance of the appropriate Command
        Command command = createCommand();
        // set the state on the (hopefully brand new) Command instance
        command.setState(commandState);
        return command.execute();
    }

    protected Command createCommand() {
        // notice the Spring API dependency!
        return this.applicationContext.getBean("command", Command.class);
    }

    public void setApplicationContext(
            ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

查找方法注入

        查找方法注入是容器覆盖管理bean上的方法的能力,以便返回容器中另一个命名bean的查找结果。查找方法通常涉及原型bean。 Spring框架通过使用CGLIB库生成的字节码来生成动态子类重写的方法实现此注入。

        如果想让这个动态子类正常工作,那么Spring容器所继承的Bean不能是final的,而覆盖的方法也不能是final的。

        对具有抽象方法的类进行单元测试时,需要开发者对类进行子类化,并提供抽象方法的具体实现。

        组件扫描也需要具体的方法,因为它需要获取具体的类。

        另一个关键限制是查找方法不适用于工厂方法,特别是在配置类中不使用@Bean的方法。因为在这种情况下,容器不负责创建实例,因此不能在运行时创建运行时生成的子类。

对于前面代码片段中的CommandManager类,Spring容器动态地覆盖createCommand()方法的实现。 CommandManager类不再拥有任何的Spring依赖,如下:

package fiona.apple;

// no more Spring imports!

public abstract class CommandManager {

    public Object process(Object commandState) {
        // grab a new instance of the appropriate Command interface
        Command command = createCommand();
        // set the state on the (hopefully brand new) Command instance
        command.setState(commandState);
        return command.execute();
    }

    // okay... but where is the implementation of this method?
    protected abstract Command createCommand();
}

在包含需要注入方法的客户端类中 (在本例中为CommandManager)注入方法的签名需要如下形式:

<public|protected> [abstract] <return-type> theMethodName(no-arguments);

如果方法是abstract的, 那么动态生成的子类会实现该方法。否则,动态生成的子类将覆盖原始类定义的具体方法。例如:

<!-- a stateful bean deployed as a prototype (non-singleton) -->
<bean id="myCommand" class="fiona.apple.AsyncCommand" scope="prototype">
    <!-- inject dependencies here as required -->
</bean>

<!-- commandProcessor uses statefulCommandHelper -->
<bean id="commandManager" class="fiona.apple.CommandManager">
    <lookup-method name="createCommand" bean="myCommand"/>
</bean>

当需要新的myCommand bean实例时,标识为commandManager的bean会调用自身的createCommand()方法.开发者必须小心部署myCommand bean为原型bean. 如果所需的bean是单例的,那么每次都会返回相同的myCommand bean实例.

另外,如果是基于注解的配置模式,你可以在查找方法上定义@Lookup注解,如下:

public abstract class CommandManager {

    public Object process(Object commandState) {
        Command command = createCommand();
        command.setState(commandState);
        return command.execute();
    }

    @Lookup("myCommand")
    protected abstract Command createCommand();
}

或者,更常见的是,开发者也可以根据查找方法的返回类型来查找匹配的bean,如下

public abstract class CommandManager {

    public Object process(Object commandState) {
        MyCommand command = createCommand();
        command.setState(commandState);
        return command.execute();
    }

    @Lookup
    protected abstract MyCommand createCommand();
}

        注意开发者可以通过创建子类实现lookup方法,以便使它们与Spring的组件扫描规则兼容,同时抽象类会在默认情况下被忽略。这种限制不适用于显式注册bean或明确导入bean的情况。

        另一种可以访问不同生命周期的方法是ObjectFactory/Provider注入。

        您可能还会发现ServiceLocatorFactoryBean(在org.springframework.beans.factory.config包中)很有用。

替换任意方法

        从前面的描述中,我们知道查找方法是有能力来覆盖任何由容器管理的bean方法的。开发者最好跳过这一部分,除非一定需要用到这个功能。

        通过基于XML的元数据配置,开发者可以使用replaced-method元素来替换已存在方法的实现。考虑以下类,它有一个我们想要覆盖的名为computeValue 的方法:

public class MyValueCalculator {

    public String computeValue(String input) {
        // some real code...
    }

    // some other methods...
}

实现org.springframework.beans.factory.support.MethodReplacer接口的类提供了新的方法定义,如以下示例所示:

/**
 * meant to be used to override the existing computeValue(String)
 * implementation in MyValueCalculator
 */
public class ReplacementComputeValue implements MethodReplacer {

    public Object reimplement(Object o, Method m, Object[] args) throws Throwable {
        // get the input value, work with it, and return a computed result
        String input = (String) args[0];
        ...
        return ...;
    }
}

如果需要覆盖bean方法的XML配置如下类似于以下示例:

<bean id="myValueCalculator" class="x.y.z.MyValueCalculator">
    <!-- arbitrary method replacement -->
    <replaced-method name="computeValue" replacer="replacementComputeValue">
        <arg-type>String</arg-type>
    </replaced-method>
</bean>

<bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/>

您可以在<replaced-method/>元素中使用一个或多个 元素来指示被覆盖的方法的方法。当需要覆盖的方法存在重载方法时,必须指定所需参数。 为了方便起见,字符串的类型会匹配以下类型,它完全等同于java.lang.String

java.lang.String
String
Str

因为,通常来说参数的个数已经足够区别不同的方法,这种快捷的写法可以省去很多的代码。

标签:Spring,Object,bean,command,Command,方法,public,注入
From: https://blog.csdn.net/m0_54144956/article/details/140440314

相关文章

  • Spring study
    IoC容器初识IoC1.什么是IoC容器?IoC容器是Spring框架的核心组成部分,它负责管理应用程序中对象的创建、配置和生命周期。IoC容器通过依赖注入(DependencyInjection,DI)的方式,自动装配和管理对象之间的依赖关系,从而避免了对象之间硬编码的依赖。2.为什么会有IoC容器?在传统的编程......
  • 字典映射简单方法
      通过反射简单设置字典,不用每个需要用字典的地方都重新写一遍 /***@paramdictType字典type*@paramdictField字典type对应字段名*@paramdictFieldName需要填充中文的字段名*@param<T>*/<T>voidsetDictName(Tobj,StringdictType,StringdictField,S......
  • mybatisPlus使用sql注入器实现真正批量插入
    注入器packagecom.ruoyi.framework.interceptor;importcom.baomidou.mybatisplus.core.injector.AbstractMethod;importcom.baomidou.mybatisplus.core.injector.DefaultSqlInjector;importcom.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn......
  • Spring Boot Vue 毕设系统讲解 11【协同过滤方法教学】
    目录1.基础知识用户基于的协同过滤(User-basedCF)物品基于的协同过滤(Item-basedCF)优缺点实际应用2.项目功能实战1.基础知识协同过滤(CollaborativeFiltering,CF)是一种广泛应用于推荐系统中的算法,它通过分析和利用用户与物品之间的交互信息来发现用户可能感兴趣......
  • SpringBoot实战:轻松实现接口数据脱敏
    引言在现代的互联网应用中,数据安全和隐私保护变得越来越重要。尤其是在接口返回数据时,如何有效地对敏感数据进行脱敏处理,是每个开发者都需要关注的问题。本文将通过一个简单的SpringBoot项目,介绍如何实现接口数据脱敏。一、接口数据脱敏概述1.1接口数据脱敏的定义接口数据脱......
  • 学习总结:数据分析方法(侧重于解决实际问题)
    目录一、战略与组织SWOT分析PEST分析BSC平衡计分卡波特五力模型BCG矩阵GE矩阵二、质量与生产TPMTQM六西格玛OPTPDCAAUDIT法(汽车行业)三、营销服务STP分析4Ps普销组合SPIN销售法安索夫矩阵推销方格理论哈夫模型四、财务管理z-SCORE模型ABC成本法杜邦分......
  • 内网穿透的10种方法
    1.使用FRP进行内网穿透FRP是一款开源的内网穿透工具,它可以帮助用户在没有公网IP或动态IP的情况下访问内网应用。只需要在内网机器上安装FRP客户端,并在公网机器上配置FRP服务端,即可实现内网穿透。FRP支持TCP和UDP协议,同时还提供了HTTP和HTTPS转发的功能,非常方便实用。 ......
  • 基于SpringBoot网络安全科普小程序
    摘要随着科技的快速的发展和网络信息的普及,信息化管理已经融入到了人们的日常生活中,各行各业都开始采用信息化管理系统,通过计算机信息化管理,首先可以减轻人们工作量,而且采用信息化管理数据信息更加的严谨,可以直接实现智能化管理和数据存储。同样这样的技术也可以直接应用到网......
  • 基于SpringBoot+MySQL+SSM+Vue.js的购物商城系统(附论文)
    获取见最下方名片获取见最下方名片获取见最下方名片演示视频基于SpringBoot+MySQL+SSM+Vue.js的购物商城系统(附论文)技术描述开发工具:Idea/Eclipse数据库:MySQLJar包仓库:Maven前端框架:Vue/ElementUI后端框架:Spring+SpringMVC+Mybatis+SpringBoot文字描......
  • 基于SpringBoot+MySQL+SSM+Vue.js的家政公司服务平台系统(附论文)
    获取见最下方名片获取见最下方名片获取见最下方名片演示视频基于SpringBoot+MySQL+SSM+Vue.js的家政公司服务平台系统(附论文)技术描述开发工具:Idea/Eclipse数据库:MySQLJar包仓库:Maven前端框架:Vue/ElementUI后端框架:Spring+SpringMVC+Mybatis+SpringBoo......