I have some beans like this:
@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 {
And I have controll bean for this beans:
@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 ;
}
}
How can I fill handlers map
in BeanManager
when start server?
I know 3 ways for this:
1) fill map in costructor:
public BeanManager(First first, Second second, Third third){
handlers.put(Type.TYPE1, first);
handlers.put(Type.TYPE2, second);
handlers.put(Type.TYPE3, third);
}
I don't need annotations, but this approach is terrible and I brought it to complete the picture.
2) fill map in 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);
}
In this solution BeanManager
contains context
and when I will use BeanManager
in my code it will pull the context. I do not like this approach.
3) move move the search for annotations in bins to BeanPostProcessor
and add setter to 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;
}
}
But in this solution I do not like setHandler
method.