SpringBoot根据注解动态执行类中的方法实现
作者:benben044
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 { @Override public String sayHello() { System.out.println("测试: father1"); return "father1"; } }
4)FatherTwo.java
模拟ServiceImpl实现类2
@Component @Extension(bizScene="test", useCase="two") public class FatherTwo implements Father{ @Override public String sayHello() { System.out.println("测试: father2"); return "father2"; } }
5)ExtInitiator.java
项目启动时的一部分初始化
@Component public class ExtInitiator { @Autowired ExtRespository extRespository; @Autowired private ApplicationContext applicationContext; @PostConstruct public 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
到此这篇关于SpringBoot根据注解动态执行类中的方法实现的文章就介绍到这了,更多相关SpringBoot 动态执行类中方法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!