流程示意:getBeansOfType方法可以根据接口类型返回相应的所有bean。
定义视频发布接口
public interface VideoPublishService {
/**
* 上传信息
*
* @param payload 上传信息荷载
* @return 返回值外部作品id
*/
Result publish(T payload);
}
工厂类
@Slf4j
@Component
public class VideoPublishDispatchService {
private HashMap mediaMap = Maps.newHashMap();
@Autowired
private ApplicationContextUtils applicationContextUtils;
/**
* 初始化授权服务
*/
@PostConstruct
public void init() throws Exception {
ApplicationContext context = applicationContextUtils.getApplicationContext();
// 得到所有的实现类
Map beanMap = context.getBeansOfType(VideoPublishService.class);
for (Map.Entry mediaPublishServiceEntry : beanMap.entrySet()) {
Class> targetClass = AopUtils.getTargetClass(mediaPublishServiceEntry.getValue());
ChannelService channelServiceInfo = targetClass.getAnnotation(ChannelService.class);
if(null == channelServiceInfo){
log.error('渠道名称未设置,class:{},channel:{}',targetClass.getName(), ChannelService.class.getName());
throw new Exception('服务:'+targetClass.getName()+' 需要配置对应的渠道名称');
}
mediaMap.put(channelServiceInfo.channel().getChannelId(),mediaPublishServiceEntry.getValue());
}
}
/**
* 获取服务
*
* @param channelId 服务类型
* @return
*/
public MediaPublishService getService(String channelId) {
return mediaMap.get(channelId);
}
}
/**
* 上下文获取工具类
*/
@Slf4j
@Component
public class ApplicationContextUtils implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext() {
return this.applicationContext;
}
}
自定义Service注解@ChannelService
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ChannelService {
@AliasFor(annotation = Component.class)
String value() default '';
/**
* 渠道名称
* @return
*/
ChannelEnum channel();
}
设计一个分发系统,对视频或文进行多种渠道的分发,发布渠道类型被设计成视频、文、音频、短文本等,针对不同的发布内容,需要分发至不同的发布渠道,我们需要一个发布接口,并且这些不同的发布渠道需要实现这个发布接口,这就涉及到了接口实现类的动态调用。
@AliasFor表示别名,它可以注解到自定义注解的两个属性上,表示这两个互为别名,也就是说这两个属性其实同一个含义。此处的别名是使用Component而不是Service,看一下Service注解,它的别名已经是Component了
定义视频发布接口实现类
@ChannelService(value = 'bilibiliVideoPublishService', channel = ChannelEnum.BILIBILI)
public class BilibiliVideoPublishServiceImpl implements VideoPublishService {
@Override
public Result publish(BilibiliPayload payload) {
return '哔哩哔哩发布成功!';
}
}
@ChannelService(value = 'kuaishouVideoPublishService', channel = ChannelEnum.KUAISHOU)
public class KuaishouVideoPublishServiceImpl implements VideoPublishService {
@Override
public Result publish(KuaishouPayload payload) {
return '快手发布成功!';
}
}
渠道类型枚举定义
public enum ChannelEnum {
KUAISHOU('kuaishou', '快手'),
DOUYIN('douyin', '抖音'),
BILIBILI('bilibili', '哔哩哔哩');
}
调用
文章为作者独立观点,不代表股票交易接口观点