1、需求
有一个接口提供了xx的服务,有两个场景分别实现了xx的具体逻辑,标记为xx1和xx2。
然后场景一过来的时候执行xx1逻辑,场景二过来的时候执行xx2逻辑。
2、简单实现
定义一个service层,提供xx的接口。
然后定义两个serviceImpl,@Service(name="")标记不同的名称,分别提供xx的具体实现。
在使用时,通过@Resource(name="")注入两个组件。
接着硬编码,当场景一时调用组件1的xx方法,当场景二时调用组件2的xx方法。
这种方法可读性较高,逻辑也清晰,但是扩展性不高,硬编码的硬伤。
3、通过自定义注解的方式
(1)实现方案
首先,构造一个自定义注解@Extension,用于存放场景所需的信息。
其次,定义一个Service接口提供xx服务
然后,定义两个ServiceImpl类实现接口的xx服务,并且标记@Service注解。同时新增@Extension注解,输入场景信息。
接着,定义一个@PostConstruct方法,在方法中读取容器中所有带@Extension注解的示例,将注解的场景信息作为key,示例作为Object放入某个组件ExtRespository的Map中存起来。
最后,请求过来时解析场景信息,从ExtRespository的Map中读取实例信息,通过Function<T,R>函数式编程调用接口的xx方法。
(2)实现示例
1)Extension.java
自定义注解接口
/*** 自定义注解*/
@Retention(RetentionPolicy.RUNTIME) // 作用于运行时
@Target(ElementType.TYPE) // 作用于类上
@Component
public @interface Extension {String bizScene() default "defaultBizScene";String useCase() default "defaultUseCase";
}
2)Father.java
模拟Service接口
public interface Father {public String sayHello();
}
3)FatherOne.java
模拟ServiceImpl实现类1
@Component
@Extension(bizScene="test", useCase="one")
public class FatherOne implements Father {@Overridepublic String sayHello() {System.out.println("测试: father1");return "father1";}
}
4)FatherTwo.java
模拟ServiceImpl实现类2
@Component
@Extension(bizScene="test", useCase="two")
public class FatherTwo implements Father{@Overridepublic String sayHello() {System.out.println("测试: father2");return "father2";}
}
5)ExtInitiator.java
项目启动时的一部分初始化
@Component
public class ExtInitiator {@AutowiredExtRespository extRespository;@Autowiredprivate ApplicationContext applicationContext;@PostConstructpublic void init(){Map<String, Object> extensionBeans = applicationContext.getBeansWithAnnotation(Extension.class);for(Object bean : extensionBeans.values()){Class<?> extensionClz = ClassUtils.getUserClass(bean);Extension extension = AnnotationUtils.findAnnotation(extensionClz, Extension.class);String bizScene = extension.bizScene();String useCase = extension.useCase();extRespository.getExtRepository().put(bizScene + "_" + useCase, bean);}}
}
6)ExtRespository.java
组件提供map的存放
@Component
public class ExtRespository {private Map<String, Object> extRepository = new HashMap<>();public Map<String, Object> getExtRepository(){return extRepository;}
}
7)Test方法中测试
@Autowired
ExtRespository extRespository;@Test
public void testExtension() {Function<Father, String> exeFunction = extention -> extention.sayHello();System.out.println("test_two场景下调用sayHello:" + exeFunction.apply((Father)extRespository.getExtRepository().get("test_two")));
}
运行测试方法时显示:
测试: father2
test_two场景下调用sayHello:father2