在項目中由於各種需要我們會自定義各種註解,就比如像Redis的訂閱和發佈,那麼我們就會有查找所有使用了指定註解的方法的需求,並對這些方法做一些統一的操作,把這個需求封裝到一個註解掃描器的抽象類工具中,不同的自定義註解去各自實現,這樣就會方便很多
這裏擴展了Spring的後置處理器BeanPostProcessor類,在Bean容器實例化、依賴注入並初始化完畢時執行註解掃描操作
/**
* 註解方法通用基礎VO
*/
public class BeanMethod {
private Object bean;
private Method method;
public BeanMethod(Object bean, Method method) {
this.bean = bean;
this.method = method;
}
public Object getBean() {
return bean;
}
public void setBean(Object bean) {
this.bean = bean;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
}
/**
* 通用註解掃描器
*/
public abstract class BaseAnnotationScanner implements BeanPostProcessor {
private static final Log log = LogFactory.getLog(GeiBaseAnnotationScanner.class);
//所有的註解
private List<BeanMethod> methodList = new ArrayList<>();
protected abstract Class findAnnotationType();
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
initMethodByAnnotation(bean, findAnnotationType());
return bean;
}
/**
* 反射查找類中特定註解的方法
*/
private void initMethodByAnnotation(Object bean, Class annotationType) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(bean.getClass());
if (null != methods ) {
for (Method method : methods) {
Annotation annotation = AnnotationUtils.findAnnotation(method, annotationType);
if (null == annotation) {
continue;
}
methodList.add(new BeanMethod(bean,method));
}
}
}
public List<BeanMethod> getMethods() {
return methodList;
}
public void setMethods(List<BeanMethod> methods) {
this.methods = methodList;
}
}
具體應用如下,繼承基礎掃描器,指定註解類型即可
/**
* Redis訂閱註解掃描器
*/
@Component
public class RedisSubscriberAnnotationScanner extends BaseAnnotationScanner {
@Override
protected Class findAnnotationType() {
return RedisSubscriber.class;
}
}