Java自定义注解+动态代理实现字段注入,方法拦截

前言

前面写过自定义注解+切面的方式去做一些事情,坏处是切面注解只能用在方法上,字段注入,参数注入都无法实现,并且拓展性差,借鉴@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();
           
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值