当前位置: 首页 > news >正文

Spring 方法注入机制深度解析:Lookup与Replace Method原理与应用

引言:依赖注入的本质思考

依赖注入的核心机制本质上只有两种基本形式:构造器注入和Setter方法注入。Spring框架中的@Autowired自动注入实际上是这两种方式的智能扩展:

  • no:无自动注入,需要手动指定

  • byNamebyType:基于Setter注入的变体

  • constructor:构造器注入的直接应用

那么,为什么通常没有提到Getter注入呢?实际上,Getter注入在特定场景下是存在的,只不过它以不同的形式呈现。

Getter注入:被忽视的依赖管理方式

Getter注入是指通过Getter方法进行硬编码的"依赖注入"。这里使用引号是因为它本质上是硬编码的,并非传统意义上的依赖注入。其核心思想是通过子类化并重写Getter方法,或者利用反射机制(常见于Mock测试库)来动态替换Getter的实现逻辑。

示例代码分析:

java

public class ClassUnderTest{ public void saySomething(){System.out.println(getString());}protected String getString(){return "Hello World";}
}public class GetFrench extends ClassUnderTest{@Override protected String getString(){return "Bonjour le monde";}
}

关键洞察:

  • 依赖项性质判断:需要明确依赖项是普通对象还是工厂对象

  • 工厂模式的自然体现:子类重写本质上就是"工厂方法"模式,返回不同的对象实例

  • IoC容器的角色:在Spring框架中,这种子类化工作由Spring CGLIB代理完成

Spring方法注入机制详解
核心概念辨析

lookup-methodreplaced-method虽然都涉及方法级别的干预,但解决的问题域完全不同:

  • lookup-method:专注于解决无状态Bean依赖有状态Bean的问题,是方法级别的对象获取机制

  • replaced-method:实现方法实现的动态替换,属于行为修改范畴

1. Lookup Method(查找方法注入)

设计目的:
允许单例作用域的Bean在每次调用特定方法时都能获取到新的原型作用域Bean实例,解决单例Bean中无法正确注入原型Bean的经典问题。

实现原理:

  • 通过XML配置或@Lookup注解声明查找方法

  • Spring运行时动态生成CGLIB子类

  • 子类重写目标方法,每次调用时向容器请求新的Bean实例

配置示例:

xml

<!-- 原型作用域的Bean -->
<bean id="myCommand" class="fiona.apple.AsyncCommand" scope="prototype"><!-- 依赖注入配置 -->
</bean><!-- 单例Bean使用lookup-method -->
<bean id="commandManager" class="fiona.apple.CommandManager"><lookup-method name="createCommand" bean="myCommand"/>
</bean>

注解方式:

java

public abstract class CommandManager {public Object process(Object commandState) {Command command = createCommand();command.setState(commandState);return command.execute();}@Lookup("myCommand")protected abstract Command createCommand();
}
2. Replaced Method(方法实现替换)

设计目的:
完全替换现有Bean中具体方法的实现逻辑,在不修改源代码的情况下实现方法行为的动态变更。

实现机制:

  • 实现MethodReplacer接口定义新的方法逻辑

  • 通过XML配置关联目标方法和替换器

  • Spring创建CGLIB代理拦截方法调用

完整示例:

java

// 原始Bean类
public class MyValueCalculator {public String computeValue(String input) {// 原始业务逻辑return "Original: " + input;}
}// 方法替换器实现
public class ReplacementComputeValue implements MethodReplacer {public Object reimplement(Object target, Method method, Object[] args) throws Throwable {String input = (String) args[0];// 新的业务逻辑return "Replaced: " + input.toUpperCase();}
}

xml

<!-- XML配置 -->
<bean id="myValueCalculator" class="x.y.z.MyValueCalculator"><replaced-method name="computeValue" replacer="replacementComputeValue"><arg-type>String</arg-type></replaced-method>
</bean><bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/>
应用场景对比分析
Lookup Method适用场景
  • 单例依赖原型:单例服务需要每次使用新的DAO实例

  • 命令模式实现:命令处理器需要创建新的命令对象

  • 状态隔离:避免在单例中意外缓存或重用原型Bean

Replaced Method适用场景
  • 行为热插拔:运行时动态切换算法或策略

  • 第三方库增强:修复或增强无法修改源码的第三方类

  • 测试模拟:集成测试中快速模拟复杂依赖

  • 轻量级AOP:当标准AOP显得过于重量级时的替代方案

技术实现深度解析
核心实现流程
  1. Bean定义合并阶段

    • 检查@Lookup注解并构建MethodOverrides

    • 处理XML中配置的replaced-method声明

  2. Bean实例化阶段

    java

    // 简化版的实例化流程
    createBeanInstance
    → checkLookupMethods()        // 检查Lookup注解
    → determineConstructors()     // 确定构造器
    → instantiateWithMethodInjection()  // 使用方法注入实例化
    → CglibSubclassCreator.instantiate() // CGLIB子类化
  3. CGLIB代理生成

    • 创建目标Bean的增强子类

    • 设置方法拦截器回调

    • 实现方法级别的行为重写

拦截器机制

Lookup方法拦截器:

java

private static class LookupOverrideMethodInterceptor implements MethodInterceptor {public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {LookupOverride lo = getLookupOverride(method);// 关键:每次调用都从容器获取新实例return this.owner.getBean(lo.getBeanName());}
}

Replace方法拦截器:

java

private static class ReplaceOverrideMethodInterceptor implements MethodInterceptor {public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {ReplaceOverride ro = getReplaceOverride(method);MethodReplacer mr = this.owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class);// 关键:使用替换器的实现逻辑return mr.reimplement(obj, method, args);}
}
现代Spring开发的最佳实践
选择建议

优先使用Lookup Method当:

  • 单例Bean需要每次获取新的原型实例

  • 核心需求是对象获取而非行为修改

考虑Replaced Method当:

  • 需要完全替换现有方法实现

  • 无法修改原始源代码

  • AOP方案过于复杂

现代替代方案
  1. @Lookup注解:比XML配置更现代简洁

  2. 策略模式:通过依赖注入不同的实现来替换行为

  3. Spring AOP:使用@Around通知实现更灵活的方法拦截

重要限制说明
  • 工厂方法不适用:两种机制都不适用于@Bean配置的工厂方法

  • CGLIB要求:目标类不能是final,必须有默认构造器

  • 性能考量:动态代理会带来轻微的性能开销

总结

Spring的方法注入机制提供了强大的扩展能力,lookup-method解决了单例获取原型实例的核心难题,而replaced-method实现了方法行为的动态替换。理解两者的本质区别和适用场景,能够帮助开发者在合适的场景选择合适的技术方案。

在现代Spring开发中,虽然这些机制的使用频率有所下降,但它们背后的设计思想仍然具有重要的学习价值,特别是在理解Spring IoC容器的工作原理和扩展机制方面。

http://www.dtcms.com/a/483288.html

相关文章:

  • 一套三维研发设计软件可以多人共享的解决方案
  • 网站模板使用网上怎么样挣钱
  • 企业网站设计制作 公司网站建设服务
  • 数据库系统安全机制设立
  • 简述网站建设基本步骤夸克观看免费视频
  • 985建设网站专业网站设计制作服务
  • 单位做网站我的网站要怎样做才能让人家搜到
  • 服务器高效操作指南:Python 环境退出与 Linux 终端快捷键全解析
  • 台州专业网站建设济南莱芜最新消息
  • 网站服务器地址在哪里看通用企业手机网站模板
  • 海口网站模板系统深圳网站建设定制开发
  • 【数据结构——最小生成树与Kruskal】
  • 前端开发中 SCSS 变量与 CSS 变量的区别与实践选择,—— 两种变量别混为一谈
  • JS基础事件处理与CSS常用属性全解析(附实战示例)
  • wordpress主题删不掉辽宁seo推广公司
  • 网站制作镇江网站常见错误
  • JavaScript 的try使用方法和应用场景
  • 网站建设页面设计规格免费论坛申请无广告
  • 【课堂笔记】LU分解,Cholesky分解
  • 巴中做网站政务网站模版
  • Ubuntu /usr/include/x86_64-linux-gnu目录的作用浅谈
  • 当“养鲜”遇见“小说家”:容声打造跨越虚实的养鲜宇宙
  • 设计模式篇之 命令模式 Command
  • 5G车联网智能终端设备TBOX
  • 河南送变电建设有限公司网站部署自己做的网站吗
  • 网站建设收费标准好么校园网站开发目的
  • 3.4 滑动窗口协议
  • 企业网站建设中存在的主要问题会有哪些?济南软件优化网站建设
  • 在 ARM 版 MacBook 上构建 lldb-mi
  • 重庆大渡口建设网站微网站 微信网站