目的是通過註解將特定類的信息(如接口編號)與類關聯,之後可通過接口編號獲取對應bean來執行對應邏輯。
1.新建註解類:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Service
public @interface ServiceCode {
String code() default "";
String className() default "";
}
包含接口編號和beanName信息。
2.新建接口類:
@ServiceCode(code = "100010", className = "echoService")
@Service("echoService")
public class EchoService {
}
3.實現接口ApplicationListener來監聽spring容器初始化完成後執行:
@Component
@Order(1)
public class ServiceInitListener implements ApplicationListener<ContextRefreshedEvent> {
private static final Logger LOGGER = LoggerFactory.getLogger(ServiceInitListener.class);
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext applicationContext = event.getApplicationContext();
//注意 需要時根容器才能通過註解獲取到bean,比如event直接獲取的容器中只有一些公共註冊bean
if (applicationContext.getParent() != null) {
applicationContext = applicationContext.getParent();
}
Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(ServiceCode.class);
for (Object bean : beansWithAnnotation.values()) {
ServiceCode annotation = bean.getClass().getAnnotation(ServiceCode.class);
String code = annotation.code();
String className = annotation.className();
//註冊接口編號和beanName
//在統一入口可通過code獲取beanName,然後通過springContext獲取對應bean執行自定義邏輯
//或者完成其他邏輯
}
}
}
注意:
ContextRefreshedEvent獲取到的上下文環境不是根spring容器,其中只有部分spring內置bean,無法通過註解獲取到自定義bean,需要獲取其父容器來完成操作。我第一次獲取是beanList總爲空,後來發現其容器內部bean沒有自定義的service bean,獲取父容器後操作一切正常。
通過@Order註解來定製執行順序,越小越優先執行。