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 .
Let change approche a little bit
@Component
public class BeanManager {
private Map<Type, Handler> handlers = new HashMap<>();
//haven't tested, just an idea : )
@Autowired
public void setHandler(List<Handler> handlersList) {
for(Handler handler : handlers) {
Type type = handler.getClass().getAnnotation(MyAnnotation.class).type();
handlers.put(type, handler);
}
}
}
If you need more inspiration, check this out LINK
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.