在Java Spring中动态解析依赖关系的最佳方法?

时间:2018-07-06 09:22:17

标签: java spring

假设我具有以下代码结构:

public class NotificationService {
     public void send(Notification notification) {
         // call other services and send the notification
     }
}

public class OrderNotification implements Notification {

    @Autowired
    public TranslationService translationService;

    private String orderNumber;

    public OrderNotification(String orderNumber) {
        this.orderNumber = orderNumber;
    }

    public String getMessage() {
        return translationService.trans('notification.order', new Object[]{orderNumber});
    }
} 

所以,我的目标是以这种方式使用NotificationService

notificationService.send(new OrderNotification(orderNumber));

但是我知道上面的代码不起作用,因为translationService不会被解析。

我的目标是将自定义参数传递给我的Notification类,并能够使用该类中的服务。春季最好的方法是什么?

2 个答案:

答案 0 :(得分:2)

我知道以下不是您问题的正确答案。但是,将EntitiesServices组合在一起是一种不良的设计模式。 Entity仅应包含有关对象的信息,而不应包含业务逻辑。 Service包含所有业务逻辑。

您需要将ServiceEntity分开。

OrderNotification看起来像一个常规实体。该实体不应包含业务逻辑。您需要针对业务逻辑的特定服务。

public class OrderNotification implements Notification {

    private String orderNumber;

    public OrderNotification(String orderNumber) {
        this.orderNumber = orderNumber;
    }

    public String getMessage() {
        return "Order number: " + orderNumber;
    }

    //Getter & Setters
    ...
} 

@Service
public class NotificationService {

    @Autowired
    public TranslationService translationService;

    public void send(Notification notification) {
        //I do not know what trans accepts, so I assume it can accept Notification
        translationService.trans(notification.getMessage());
    }
}

如果您确实需要结合实体和服务-那么我推荐这种方法:

@Service
public class Master{

    @Autowired
    NotificationService notificationService

    public void testMethod(){
        Notification notification = notificationService.createOrder("order1");
        notificationService.send(notification);
    }

}

@Service
public class NotificationService {

    @Autowired
    public TranslationService translationService;

    public Notification createOrder(String orderNumber){
        return new OrderNotification(orderNumber, translationService);
    }

    public void send(Notification notification) {
        // call other services and send the notification
        notification.getMessage();
    }
}


public class OrderNotification implements Notification {

    private TranslationService translationService;

    private String orderNumber;

    //I have changed this constructor to accept TranslationService.
    public OrderNotification(String orderNumber, TranslationService translationService) {
        this.orderNumber = orderNumber;
        this.translationService = translationService;
    }

    public String getMessage() {
        return translationService.trans('notification.order', new Object[]{orderNumber});
    }
} 

答案 1 :(得分:0)

您的可用选项很少:

  1. 配置AOP并加载编织时间,以处理使用new关键字创建的对象上的Spring注释。 5.8.1. Using AspectJ to dependency inject domain objects with Spring文档对此进行了解释。

  2. OrderNotification声明为原型作用域bean,并使用BeanFactory.getBean(Class<T> requiredType, Object... args)方法从上下文中获取每个实例。

    String orderNumber = "123";
    OrderNotificaton = factory.getBean(OrderNotificaton.class, orderNumber);
    
  3. 拖放@Autowired并使用普通的构造函数注入。

    public OrderNotification(TranslationService translationService, String orderNumber) {
        this.translationService = Objects.requireNonNull(translationService);
        this.orderNumber = Objects.requireNonNull(orderNumber);
    }
    

如果您只需要简单的@Autowired,我会选择选项3。这是最简单的方法,并且由于您不必依赖Spring,因此使编写单元测试更加容易。