Spring Cloud Config 解决单例 Bean 依赖非单例 Bean

本文探讨了在Spring应用中,如何处理单例Bean依赖非单例Bean的问题。通过介绍Lookup method注入、任意方法替换以及Spring Config解决方案,详细阐述了如何动态获取Bean的新实例。在Spring Cloud Config中,@RefreshScope注解用于实现属性的动态刷新,通过BeanFactory获取新Bean,确保每次获取的都是最新的实例。
摘要由CSDN通过智能技术生成

在大多数应用程序场景中,容器中的大多数 bean 都是单例的。当一个单例 bean 需要与另一个单例 bean 协作,或者一个非单例 bean 需要与另一个非单例 bean 协作时,您通常通过将一个bean 定义为另一个 bean 的属性来处理依赖关系。当 bean 的生命周期不同时,问题就出现了。假设单例 bean A 需要使用非单例(原型) bean B,可能是在 A 上的每个方法调用上。容器只创建一次单例 bean A,因此只有一次机会设置属性。容器不能在每次需要 bean B 的新实例时为 bean A 提供一个。

一个解决方案是放弃一些控制反转。您可以通过实现 ApplicationContextAware 接口,并在 bean A 每次需要 bean B 实例时向容器发出 getBean(“B”) 调用来请求(通常是新的) bean B 实例,从而使 bean A 感知到容器。下面是这种方法的一个例子:

// a class that uses a stateful Command-style class to perform some processingpackage fiona.apple;// Spring-API importsimport 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;    }}

前面的方法是不可取的,因为业务代码知道 Spring 框架并与之耦合。方法注入是 Spring IoC 容器的一种高级特性,它允许以一种干净的方式处理这个用例。

1、Lookup method 注入

查找方法注入是容器覆盖容器托管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);

如果方法是抽象的,则动态生成的子类实现该方法。否则,动态生成的子类将重写在原始类中定义的具体方法。例如:

<!-- a stateful bean deployed as a prototyp
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值