前言
前面写过自定义注解+切面的方式去做一些事情,坏处是切面注解只能用在方法上,字段注入,参数注入都无法实现,并且拓展性差,借鉴@Autowire依赖注入在bean初始化的时候做一些操作,就可以显现字段的注入,也能检测哪些bean有自定义注解;同时借鉴使用动态代理就能实现注解的多功能。
了解
bean生命周期中有很多地方都能参与到bean的初始化过程中,此次实现BeanPostProcessor接口,BeanPostProcessor接口中有两个方法
public interface BeanPostProcessor {
//bean初始化方法调用前被调用
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
//bean初始化方法调用后被调用
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
这两个方法均参与bean初始化的历程中,bean类似于流水从参数流入,返回值流出,如果在方法中代理传入的bean,并返回代理对象就可以实现动态bean代理
/**
* @author jiang
*/
@Component
public class AnnotationsImpl implements BeanPostProcessor, ApplicationContextAware, ApplicationRunner {
private ApplicationContext applicationContext;
private Set<Object> annotationBeans = new HashSet<>();
@Bean("injectBeans")
public Map<String, Object> injectBeans(){
return new ConcurrentHashMap<>();
}
@Resource(name = "injectBeans")
private Map<String, Object> injectBeans;
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
Class<?> targetCls = bean.getClass();
Set<AnnotationProcessor> annotationProcessors = new HashSet<>();
//获取自定义注解实现类,自定义注解需实现AnnotationProcessor接口
Map<String, AnnotationProcessor> res = applicationContext.getBeansOfType(AnnotationProcessor.class);
//将所有的自定义注解实现类记录,用于自定义注解实现类区分注解
annotationBeans.addAll(res.values());
Method[] declaredMethods = targetCls.getDeclaredMethods();
//每个bean检测自定义注解
for (AnnotationProcessor value : res.values()) {
Class annotationClass = value.targetAnnotation();
Annotation clazzAnnotation = AnnotationUtils.findAnnotation(targetCls, annotationClass);
if (clazzAnnotation != null){
//如果bean检测到类注解,执行自定义方法
value.classInit(value.targetAnnotation(), bean);
}
//检测bean字段是否有自定义注解
Field[] allFields = FieldUtils.getAllFields(targetCls);
for (Field allField : allFields) {
Annotation fieldAnnotation = AnnotationUtils.findAnnotation(allField, annotationClass);
if (fieldAnnotation != null){
try {
Map<String, Object> map = new HashMap<>();
map.put("Bean", bean);
map.put("Field", allField);
map.put("AnnotationProcessor", value);
//如果字段有自定义注解,则记录下来,为啥要记录呢?卖个关子
injectBeans.put(bean.getClass().getName()+allField.getName(), map);
} catch (Exception e) {
e.printStackTrace();