在非托管对象中使用Spring托管Bean

即使我们想使用现有的最佳和最新技术,我们也必须处理遗留代码。 想象一下,新代码是用Spring框架的最新技术编写的,而旧代码根本不是用Spring编写的。 然后在非托管Spring对象中使用Spring托管Bean是我们必须处理的模式之一。 遗留代码具有非托管的Spring对象,而我们要引用的代码是Spring托管的Bean。 我们如何解决这个问题?

创建一个Spring Bean

假设我们有一个名为TaxService的托管Spring Bean和一个名为LegacyObject的对象。 LegacyObject是遗留代码,从中可以引用托管Spring Bean上的calculateTax方法。

税务服务

package com.jdriven;

import org.springframework.stereotype.Service;

@Service
public class TaxServiceImpl
        implements TaxService {

    @Override
    public Double calculateTax(Double price) {
        return new Double(price * 0.21);
    }
}

与桥接服务方法的接口

我们定义一个包含方法列表的接口。 这些方法中的每一个都返回一个Spring托管Bean。 我们创建了一个名为getTaxService的方法来返回刚刚创建的TaxService Bean。

SpringContextBridgedServices

package com.jdriven;

/**
 * This interface represents a list of Spring Beans (services) which need to be referenced from a non Spring class.
 */
public interface SpringContextBridgedServices {
    TaxService getTaxService();
}

实施Spring Context Bridge

接下来,我们为SpringContextBridgedServices接口创建一个实现。 让我们将此类SpringContextBridge ,使其成为Spring Bean,并在该类中添加以下功能。

  1. 此类还应实现Spring的ApplicationContextAware接口。 我们需要从接口实现的方法中唯一的参数是参数ApplicationContext 。 我们将此参数保存在静态成员变量中。
  2. 创建一个静态方法以返回SpringContextBridgedServices然后让该方法返回由Spring管理的Bean。 使用applicationContext.getBean(SpringContextBridgedServices.class)返回它。
  3. 自动连接TaxService并将其返回到我们需要从SpringContextBridgedServices方法实现的方法中。

SpringContextBridge

package com.jdriven;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
* Register this SpringContextBridge as a Spring Component.
*/
@Component 
public class SpringContextBridge 
        implements SpringContextBridgedServices, ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Autowired
    private TaxService taxService; //Autowire the TaxService

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

    /**
     * A static method to lookup the SpringContextBridgedServices Bean in 
     * the applicationContext. It is basically an instance of itself, which 
     * was registered by the @Component annotation.
     *
     * @return the SpringContextBridgedServices, which exposes all the 
     * Spring services that are bridged from the Spring context.
     */
    public static SpringContextBridgedServices services() {
        return applicationContext.getBean(SpringContextBridgedServices.class);
    }

    @Override
    public TaxService getTaxService() {
        return taxService; //Return the Autowired taxService
    }
}
  • 注意1:有可能以静态方法本身返回Spring托管的bean。 我选择不这样做,因此我的静态方法较少,以后可以模拟一些参考服务。
  • 注2:最终,您希望将这两种功能分开。 一个持有ApplicationContext并返回SpringContextBridgedServices Bean。 另一个是SpringContextBridgedServices Bean本身。 在这个简短的演示中,我只是将它们放在同一个Bean中。

带我去桥

现在是时候打电话给这座桥了。 就像下面的代码所示的那样简单。

传统对象

package com.jdriven;

public class LegacyObject {

    private Double price;

    public Double doTheCalculation() {
        //Get the Service from the Bridge
        TaxService taxService = SpringContextBridge.services().getTaxService();
        return taxService.calculateTax(this.price);
    }
}

灵活但不受限制的替代方案

这是限制桥接服务列表的一种方式。 仅SpringContextBridgedServices接口中提到的服务将被桥接。 如果您想要一种更灵活但受控制较少的方法,则可以重写SpringContextBridgedServices

SpringContextBridgedServicesAlternative

package com.jdriven;

public interface SpringContextBridgedServicesAlternative {

    <T> T getService(Class<T> serviceType);
}

现在我们可以通过调用SpringContextBridge.services().getService(TaxService.class)获得服务。 在这种替代方案中,我们无法控制可以桥接哪个Spring托管Bean。

翻译自: https://www.javacodegeeks.com/2015/03/using-spring-managed-bean-in-non-managed-object.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值