【发布时间】:2019-03-17 10:37:50
【问题描述】:
我有一些这样的豆子:
@MyAnnotation(type = TYPE1)
@Component
public class First implements Handler {
@MyAnnotation(type = TYPE2)
@Component
public class Second implements Handler {
@MyAnnotation(type = TYPE3)
@Component
public class Third implements Handler {
我有这个 bean 的控制 bean:
@Component
public class BeanManager {
private Map<Type, Handler> handlers = new HashMap<>();
@Override
public Handler getHandler(Type type) {
Handler handler = map.get(type);
if (handler == null)
throw new IllegalArgumentException("Invalid handler type: " + type);
return handler ;
}
}
如何在启动服务器时将handlers map填入BeanManager?
我知道 3 种方法:
1) 在构造函数中填充地图:
public BeanManager(First first, Second second, Third third){
handlers.put(Type.TYPE1, first);
handlers.put(Type.TYPE2, second);
handlers.put(Type.TYPE3, third);
}
我不需要注释,但是这种方法很糟糕,我带来了它来完成图片。
2) post costroctor(@PostConstruct)中填图:
@PostConstruct
public void init(){
Map<String, Object> beansWithAnnotation = context.getBeansWithAnnotation(MyAnnotation.class);
//get type from annotation
...
//add to map
handlers.put(type, bean);
}
在此解决方案中,BeanManager 包含 context 和 当我将在我的代码中使用 BeanManager 时,它将拉取上下文。我不喜欢这种方法。
3) 将 bins 中的注解搜索移动到 BeanPostProcessor 并将 setter 添加到 BeanManager:
@Component
public class MyAnnotationBeanPostProcessor implements BeanPostProcessor {
private final BeanManager beanManager;
public HandlerInAnnotationBeanPostProcessor(BeanManager beanManager) {
this.beanManager = beanManager;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
Annotation[] annotations = bean.getClass().getAnnotations();
for (Annotation annotation : annotations) {
if (annotation instanceof MyAnnotation) {
Type[] types = ((MyAnnotation) annotation).type();
for (Type type: types) {
beanManager.setHandler(type, (Handler) bean);
}
}
}
return bean;
}
}
但是在这个解决方案中我不喜欢setHandler 方法。
【问题讨论】:
标签: java spring spring-boot dependency-injection