我们通常会自定义一些注解加在类或者方法上面,然后在项目初始化的时候加载这些添加了自定义注解的类。如果我们在这些类或方法上还使用了其他自定义注解或者类似@Transactional注解,很可能在启动的时候会出现空指针异常。原因是用了多个注解,导致项目启动的时候拿到的是该类的代理对象,而不是原始类,可以使用getSuperclass()来获取其原始类。
例:
@Component
@Slf4j
public class HandlerDataFactory {
private Map<String, HandlerData> handlerMap = new ConcurrentHashMap(256);
@Resource
private SpringContextUtil springContextUtil;
@PostConstruct
public void init() {
//获取那些带上了@CustomAnnotation注解的处理实现类
Map<String, Object> handlerMap = springContextUtil.getContext().getBeansWithAnnotation(CustomAnnotation.class);
for (Object handler : handlerMap.values()) {
//这里如果handler.getClass()是代理对象,则customAnnotation为null
CustomAnnotation customAnnotation = handler.getClass().getAnnotation(CustomAnnotation.class);
String[] groups = customAnnotation.group();
List<String> groupList = Lists.newArrayList(groups);
groupList.forEach(group -> {
if (Objects.nonNull(handlerMap.get(group))) {
throw new RuntimeException(String.format("分组:【%s】重复,请检查!", group));
}
handlerMap.put(group, (HandlerData) handler);
});
}
//转换为只读Map
handlerMap = Collections.unmodifiableMap(handlerMap);
log.info("处理类加载完毕!size={}", handlerMap.size());
}
public Map<String, HandlerData> getHandlerMap() {
return handlerMap;
}
}
修改:
@Component
@Slf4j
public class HandlerDataFactory {
private Map<String, HandlerData> handlerMap = new ConcurrentHashMap(256);
@Resource
private SpringContextUtil springContextUtil;
@PostConstruct
public void init() {
//获取那些带上了@CustomAnnotation注解的处理实现类
Map<String, Object> handlerMap = springContextUtil.getContext().getBeansWithAnnotation(CustomAnnotation.class);
for (Object handler : handlerMap.values()) {
//这里如果handler.getClass()是代理对象,则customAnnotation为null
CustomAnnotation customAnnotation = handler.getClass().getAnnotation(CustomAnnotation.class);
//如果是代理对象,则获取其父类,即原始类
if (Objects.isNull(customAnnotation)) {
customAnnotation = handler.getClass().getSuperclass().getAnnotation(CustomAnnotation.class);
}
String[] groups = customAnnotation.group();
List<String> groupList = Lists.newArrayList(groups);
groupList.forEach(group -> {
if (Objects.nonNull(handlerMap.get(group ))) {
throw new RuntimeException(String.format("分组:【%s】重复,请检查!", group ));
}
handlerMap.put(group, (HandlerData) handler);
});
}
//转换为只读Map
handlerMap = Collections.unmodifiableMap(handlerMap);
log.info("处理类加载完毕!size={}", handlerMap.size());
}
public Map<String, HandlerData> getHandlerMap() {
return handlerMap;
}
}