开发中 利用 spring利用扩展点 applicationContextAware,BeanNameAware实现模板+策略模式

背景:比如有发送短信的功能,需要接入不同厂商。我们在调用时候只要发送厂商名称(或者其他唯一标识)即可调用。我们在项目中如何实现呢?

这里面包含了 模板模式和策略模式

实现一:

公共接口(都有发送短信的功能):

public interface IfTest {
      // 公共方法
      String send();
}

 

抽象公共类(用于放置单例的bean以及一些公共实现方法等(比如测试是否可以调通))

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

import java.util.HashMap;
import java.util.Map;

public abstract class TestBase implements ApplicationContextAware, IfTest {

    private ApplicationContext context;

    public static Map<String, IfTest> getTestServiceMap() {
        return testServiceMap;
    }

    private static Map<String, IfTest> testServiceMap = new HashMap<>();

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

    public abstract void init();

    protected void setName(Class<? extends IfTest> aClass, String name) {
        if (!testServiceMap.containsKey(name)) {
            IfTest bean = context.getBean(aClass);
            testServiceMap.put(name, bean);
        }
    }
    
}

 

不同厂商实现

@Service
public class Test1 extends TestBase {

    @Override
    public void init() {
        setName(this.getClass(), "厂商1");
    }

    @Override
    public String send() {
        System.out.println("厂商1");
        return "厂商1";
    }

}
@Service
public class Test2 extends TestBase {

    @Override
    public void init() {
        setName(this.getClass(), "厂商2");
    }

    @Override
    public String send() {
        System.out.println("厂商2");
        return "厂商2";
    }

}

调用方式:

TestBase.getTestServiceMap("厂商1").send();

 

实现二:

只有抽象类改变:

import org.springframework.beans.factory.BeanNameAware;

import java.util.HashMap;
import java.util.Map;

public abstract class TestBase2 implements BeanNameAware, IfTest {


    public static Map<String, IfTest> getTestServiceMap() {
        return testServiceMap;
    }

    private static Map<String, IfTest> testServiceMap = new HashMap<>();


    @Override
    public void setBeanName(String beanName) {
        init();
        testServiceMap.put(customerName, this);
    }

    public abstract void init();

    private String customerName;

    protected void setName(String customerName) {
        this.customerName = customerName;
    }

}

 

方式一和方式二不同点在于利用了 spring得不同扩展点、applicationcontextaware,beannameaware.目的都可以达到。

 

初始化的方法可以更优就是利用构造方法:

 

 

 

 

posted @ 2021-04-19 16:48  _Phoenix  阅读(279)  评论(0编辑  收藏  举报