如何在抽象类中优雅的注入Bean

4,885 阅读1分钟

这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战

问题

模板方法模式是我们开发的过程中经常使用的一种设计模式,将通用相同的业务逻辑抽象出来模板方法,针对个性的方法放在子类中实现。我们知道SpringBean的注入方式有很多种,这里我们介绍一个相对比较优雅的一种方式。利用类的 protected 属性特点进行注入。

回顾一下protected属性的特点

  1. 修饰的静态属性和方法
    1.1 直接调用
    1.2 实例化父类对象进行调用
    1.3 实例化子类对象进行调用
  1. 修饰的非静态属性和方法
    实例化子类对象进行调用

例子

我们可以利用修饰非静态属性通过实例化子类对象进行调用

public interface Action {

    void process(ActionContext context);
}

@Service
public class AiTouchAction extends AbstractTouchAction implements Action {
    @Override
    public void process(ActionContext context) {
        super.doProcess(context);
    }

    @Override
    protected void touch(ActionContext context) {
        System.out.println("AiTouchAction 主要的业务逻辑");
    }
}


@Service
public class SmsTouchAction extends AbstractTouchAction implements Action {
    @Override
    public void process(ActionContext context) {
        super.doProcess(context);
    }

    @Override
    protected void touch(ActionContext context) {
        System.out.println("SmsTouchAction 主要的业务逻辑");
    }
}


@Service
public abstract class AbstractTouchAction {

    @Resource
    private PaymentDAO paymentDAO;

    public void doProcess(ActionContext context) {
        // 业务主要逻辑处理
        touch(context);

        // 记账单
        paymentDAO.pay(Long.getLong(context.getTaskId().toString()));
    }

    protected abstract void touch(ActionContext context);
}


@Repository
public class PaymentDAO {

    public void pay(Long taskId) {
        // 记账单
    }
}

单测

@SpringBootTest
public class AbstractBeanTest {
    @Resource
    private SmsTouchAction smsTouchAction;

    @Resource
    private AiTouchAction aiTouchAction;

    @Test
    public void test() {
        ActionContext context = new ActionContext();
        context.setTaskId(1);
        smsTouchAction.process(context);

        aiTouchAction.doProcess(context);
    }
}