开发中 利用 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.目的都可以达到。
初始化的方法可以更优就是利用构造方法: