Spring基础——方法注入(Method Injection)

目录

  • 查找方法注入(Lookup Method)
    • 查找方法注入
      • 基于XML的方法注入
      • 基于注解的方法注入
  • Arbitrary Method Replacement(任意方法替换)

文章所用项目源码参考:java_spring_learn_repo

查找方法注入(Lookup Method)

  • 通常我们项目开发中大多都使用单例模式的Bean,因此Bean之间的依赖大多都是单例与单例之间的,而如果我们想将prototype模式的Bean被注入到单例模式的Bean中,因为单例Bean只会在创建时注入Bean的引用,所以prototype模式的Bean会一直是最开始创建的实例(换句话说就是prototype间接失效了,已经是单例模式了)。如果想要每次调用prototype模式Bean都获取一个新的实例,可以通过方法注入来实现。
  • 在Spring官方给的文档中提供了一种能在每次调用都获取新实例对象的方案,可以通过实现ApplicationContextAware接口,给Bean注入容器,然后再让Bean需要调用新实例时让容器创建一个新的实例。

ApplicationContextAware是Spring框架中的一个接口,用于让Bean实现类获取对Spring应用上下文(ApplicationContext)的引用。通过实现ApplicationContextAware接口,Bean可以在被实例化后,由Spring容器注入应用上下文的引用,从而获取容器中的其他Bean或执行一些与容器相关的操作。

  • 首先创建一个prototype的Bean
public class Command {
    private String state;

    public void setState(String state) {
        this.state = state;
    }

    public String execute() {
        return this + "对象被执行";
    }
}
  • XML配置Scope为prototype
<bean id="command" class="com.nobugnolife.method_injection.Command" scope="prototype"/>
  • 这里通过实现ApplicationContextAware来获取ApplicationContext,然后在对象每次调用process方法时都会让容器获取一个新的Command实例
public class MyApplicationContextAwareBean implements ApplicationContextAware {
    private ApplicationContext applicationContext;

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

    // 通过applicationContext创建新的Commmad实例化Bean
    protected Command createCommand() {
        return this.applicationContext.getBean("command", Command.class);
    }

    // 每次调用process时都从容器中获取新的bean实例
    public String process(String state) {
        Command command = createCommand();
        command.setState(state);
        return command.execute();
    }
}
  • 测试process调用是否为新实例
@Test
public void testMethodInjection(){
    ApplicationContext ctx = new ClassPathXmlApplicationContext("methodInjection.xml");
    MyApplicationContextAwareBean mcb = ctx.getBean(MyApplicationContextAwareBean.class);
    System.out.println(mcb.process("发送信息"));
    System.out.println(mcb.process("激活"));
    System.out.println(mcb.process("添加"));
}

test_applicationcontextaware

  • 这种方法会将Spring的代码框架耦合进项目工程中,因此官方并不推荐通过这种方法解决非单例模式Bean的调用问题,Spring也给出了通过方法注入的解决方案(有其他很多解决方案,本篇文章重点是讲方法注入)。

查找方法注入

  • 查找方法是通过在单例Bean中声明一个抽象方法,该抽象方法会在Spring容器运行时动态生成(通过CGLIB库直接生成字节码)一个子类来实现这个抽象方法,以提供prototypeBean实例。
  • 因为Spring在运行的时候是自动创建子类实现,因此要被子类实现的抽象类不能有final
  • 如果是通过工厂模式实例化Bean的话,查找方法注入是不起作用的,特别是通过@Bean注解的方式,因为此时容器不负责创建实例,所以不能动态创建运行时子类。

基于XML的方法注入

  • 首先需要定义一个查找方法的抽象类,并提供实例化Bean的抽象方法
public abstract class CommandManager {
    public String process(String commandState) {
        // 通过调用createCommand来获取新的实例Bean
        Command command = createCommand();
        command.setState(commandState);
        return command.execute();
    }

    protected abstract Command createCommand();
}
  • 在bean配置中设置lookup-method标签
<!-- 查找方法注入 -->
<bean id="commandManager" class="com.nobugnolife.method_injection.CommandManager">
    <lookup-method name="createCommand" bean="command"/>
</bean>

基于注解的方法注入

  • 注解通过Lookup注解对抽象方法进行标记即可
@Component
public abstract class CommandManager {
    public String process(String commandState) {
        // 通过调用createCommand来获取新的实例Bean
        Command command = createCommand();
        command.setState(commandState);
        return command.execute();
    }

    @Lookup
    protected abstract Command createCommand();
}

Arbitrary Method Replacement(任意方法替换)

  • 任意方法是指Spring框架中一种高级的AOP(面向切面编程)功能。通过这种方式,你可以在运行时替换类中的方法,并提供自定义的实现逻辑。
  • 要想实现任意方法替换,首先要实现org.springframework.beans.factory.support.MethodReplacer提供的方法
public class ReplacementCompute implements MethodReplacer {
    public Object reimplement(Object o, Method method, Object[] objects) throws Throwable {
        // 获取原方法传入参数
        String input = (String) objects[0];
        // 执行新的指令方法
        return "Compute方法重构:" + input;
    }
}
  • 之后部署初始类,然后指定对应实现方法覆盖的Bean
<!-- 定义原方法Bean-->
<bean id="compute" class="com.nobugnolife.method_injection.Compute">
    <!-- 使用replaced-method关联需要覆盖的方法 name为方法名 replacer为指定覆盖方法的bean -->
    <replaced-method name="ComputeValue" replacer="replacementCompute">
        <!-- 重载方法参数的签名,只有当方法重载时有多个变体时才是必要的 -->
        <arg-type>String</arg-type>
    </replaced-method>
</bean>

<bean id="replacementCompute" class="com.nobugnolife.method_injection.ReplacementCompute"/>
  • 任意方法替换的功能很灵活而且十分强大,但因为过于接近底层,而且会重构代码逻辑,容易造成非常危险的后果,因此尽量不要在开发中运用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/433862.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

高分辨率全球海洋温度和盐度再分析数据Global Ocean Physics Reanalysis(0.083°),并利用matlab读取绘图

1.引言 在研究全球海平面变化的问题中&#xff0c;卫星测高获得总的海平面变化&#xff0c;而海平面变化包含质量变化和比容变化。因此测高数据和海洋物理分析数据对于海平面研究至关重要。 测高数据下载网址&#xff1a; Global Ocean Gridded L 4 Sea Surface Heights And …

厉害了,有了这款AI智能代码助手,摸鱼新纪元来了!

大家好啊&#xff0c;欢迎来到web测评。本期给大家分享一款AI智能代码助手BaiduComate&#xff0c;让大家上班有更多的时间来摸鱼&#xff0c;俗话说的好&#xff0c;摸鱼一时爽&#xff0c;一直摸一直爽啊哈哈~~ 智能代码助手使用地址 前往BaiduComatehttps://comate.baidu.c…

3d模型怎么镜像?3d模型镜像的步骤---模大狮模型网

在3D建模软件中&#xff0c;对3D模型进行镜像操作通常是指沿着某个轴线(如X、Y、Z轴)进行镜像翻转&#xff0c;使模型在该轴线的一侧产生对称的镜像效果。以下是在常见的3D建模软件中对3D模型进行镜像的一般步骤&#xff1a; 3d模型镜像步骤&#xff1a; 选择模型&#xff1a;…

碳视野|全国首个ESG区域行动方案通过,上海政府推进ESG有八“要”

引领绿色转型&#xff0c;共筑低碳未来&#xff01;AMT企源碳管理团队深入解读碳领域政策、概念及标准&#xff0c;分享实践经验&#xff0c;助力产业绿色发展。我们启动“碳视野、碳课堂、碳实践”三大专栏&#xff0c;紧跟碳行业政策动态&#xff0c;以“科普实践分享”为核心…

小程序管理平台:助力企业数字化转型

微信小程序生态近年来发展迅猛&#xff0c;已成为中国互联网不可忽视的力量。截至2023年6月&#xff0c;微信小程序数量已超过300万&#xff0c;同比增长25%&#xff0c;涵盖了电商、生活服务、教育、金融等众多行业。微信小程序内容生态已经日趋完善&#xff0c;并满足各领域用…

windows中使用nnUNet的nnUNet_convert_decathlon_task提示路径不对

找到问题并且解决解决办法 报错时候的指令 nnUNet_convert_decathlon_task -i D:\桌面\nnUNet\DATASET\nnUNet_raw\nnUNet_raw_data\Task05_Prostate 修改为 nnUNet_convert_decathlon_task -i D:/桌面/nnUNet/DATASET/nnUNet_raw/nnUNet_raw_data/Task05_Prostate 修改点&…

Day37 socket、TCP、UDP

socket类型 流式套接字(SOCK_STREAM) TCP 提供了一个面向连接、可靠的数据传输服务&#xff0c;数据无差错、无重复的发送且按发送顺序接收。内设置流量控制&#xff0c;避免数据流淹没慢的接收方。数据被看作是字节流&#xff0c;无长度限制。 数据报套接字(SOCK_DGRAM) UD…

寻找合适的分数线

解法&#xff1a; 统计个数用数组做桶即可 #include<iostream> #include<vector> #include<algorithm> using namespace std; #define endl \n int main() {vector<int> tong(301, 0);int n, m, a;cin >> n >> m;while (n--) {cin >&…

C++——using 关键字

C++——using 关键字 using 在C++中的用途有很多,是非常就经典的关键字复用,它的作用大致可以分为三类: using 指令using 声明using 别名1. using 指令 简单点说,using 指令只能作用于命名空间,引入命名空间中的名字。 2. using 声明 2.1 对命名空间成员的 using 声明 u…

Android基础面试常常死在这几个问题上,大厂Android高级多套面试专题整理集合

前言 本人毕业于非211、985一本&#xff0c;学的是计算机网络&#xff0c;大一在一位师哥的引导下接触了Android开发&#xff0c;随着近一步的接触&#xff0c;慢慢的喜欢上了Android开发。于是大二开始&#xff0c;我开始自学Android开发。 大四的时候开始找实习工作&#x…

【OJ】日期差值与日期累加

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1. KY111 日期差值1.1 题目分析1.2 代码 2. KY258 日期累加2.1 题目分析2.2 代码 1. KY111 日期差值 1.1 题目分析 日期之间比较可能会出现给的两个年月日都不相同&#xff0c;这个就不好作差&#xff0c;每个月给的…

【论文精读】大语言模型融合知识图谱的问答系统研究

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

飞书云文档API操作详细介绍

1.场景分析 公司内部很多文档都是由多人进行维护的&#xff0c;随时发生变更&#xff0c;因此在利用这些数据的时候就需要直接读取云文档的数据&#xff0c;从而执行下一步动作。团队云文档api执行权限一般需要管理员审核才能使用。如果你就是管理员&#xff0c;那么恭喜你&am…

进程的奥德赛:并发世界中的核心概念与动态管理

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua&#xff0c;在这里我会分享我的知识和经验。&#x…

【轮式平衡机器人】——TMS320F28069片内外设之ePWM

声明&#xff1a;本系列博客参考有关专业书籍&#xff0c;截图均为自己实操&#xff0c;仅供交流学习&#xff01; 引入 脉冲宽度调制&#xff08;PWM&#xff09;是一种对模拟信号进行数字编码的方法&#xff0c;硬件原理是根据相应载荷的变化来调制晶体管栅极或基极的偏置&…

代码随想录算法训练营第11天

20. 有效的括号 方法&#xff1a; 1. 如果 !st.empty() return false2.如果st.top() ! s[i] return false3. 如果 st.empty() return false注意&#xff1a; 以下这种写法 不满足 题目要求的第二点&#xff0c;不能以正确的顺序闭合 if(s[i] st.top()){return true;s…

世界级通讯社发稿-法新社海外发稿渠道-大舍传媒

世界级通讯社发稿-法新社海外发稿渠道-大舍传媒 美联社&#xff1a;全球最大的通讯社之一 美联社&#xff08;Associated Press&#xff09;是全球最大的通讯社之一&#xff0c;成立于1846年&#xff0c;总部位于美国纽约。该社拥有一支庞大的全球新闻团队&#xff0c;涵盖了…

x86使用PID模式检测磁盘是否存在--代码实现

磁盘 视频教程以及实际代码可以看这一个教程 ATA PIO Mode - OSDev Wiki 下面的大部分来自这一个网址的翻译 在磁盘的第一个扇区里面可以有4个描述分区的描述符 电脑有两个总线, Primary Bus, Secondary Bus, 这两个都有一个Msater Driver和一个Slave Driver According to t…

Ceph qos 限速

因为1 Mbps 1,000,000 bps rbd_qos_bps_limit、rbd_qos_read_bps_limit和rbd_qos_write_bps_limit都是与RBD&#xff08;Rados Block Device&#xff09;的QoS&#xff08;Quality of Service&#xff0c;服务质量&#xff09;相关的参数&#xff0c;用于限制I/O操作的速率。这…

【EI会议征稿通知】第四届人工智能,大数据与算法国际学术会议 (CAIBDA 2024)

第四届人工智能&#xff0c;大数据与算法国际学术会议 (CAIBDA 2024) 2024 4th International Conference on Artificial Intelligence, Big Data and Algorithms 由河南省科学院、河南大学主办&#xff0c;河南省科学院智慧创制研究所、河南大学学术发展部、河南大学人工智能…