【Spring源码点滴】 @ControllerAdvice

在SpringMVC中,@Controller可以定义一个控制层Bean,其中的方法比较专注于业务,实际在应用中,通常需要对业务前后进行统一的处理,这时会告诉你可以用@ControllerAdvice注解,在其中可以完成统一处理的逻辑,那么@ControllerAdive是怎么实现的?

首先,根据@ControllerAdvice查找到和它相关的类,发现ControllerAdviceBean。

然后,发现方法findAnnotatedBeans,为静态方法,应该是初始化被调用,debug,启动应用,拦截下来,查看代码,基本逻辑就是从容器中查找@ControllerAdvice注解的Bean,然后new一个ControllerAdviceBean,放入List中返回给调用者。

调用者是谁?跟踪返回,来到RequestMappingHandlerAdapter.initControllerAdviceCache方法,在获取返回List之后,首先排序,然后遍历List。如果项目中有多个ControllerAdive,是需要排序的,可以实现Ordered接口,或者在类上面注解@Order,默认排序值为INT最大值,优先级最低。

阅读遍历的逻辑,会发现其实只是获取ControllerAdviceBean中的对应注解的方法,然后放入RequestMappingHandlerAdapter对应的缓存中,到这就明了了,这个统一处理的其实还是通过RequestMappingHandlerAdapter实现的,只是再抽象了一层MVC的模式,使开发者可以关注@ControllerAdvice注解的Bean本身。

有四种可被读取的方式,代码在最下方:

1.MODEL_ATTRIBUTE_METHODS,方法上注解RequestMapping或ModelAttribute;

2.INIT_BINDER_METHODS,方法上注解InitBinder;

3.继承RequestBodyAdvice;

4.继承ResponseBodyAdvice;

这4种方法分别有什么作用,网上的资料有很多,就不赘述了,本人偏向于分析设计思想。至于RequestMappingHandlerAdapter,放另一篇文章吧。

    for (ControllerAdviceBean adviceBean : adviceBeans) {
            Class<?> beanType = adviceBean.getBeanType();
            if (beanType == null) {
                throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
            }
            Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
            if (!attrMethods.isEmpty()) {
                this.modelAttributeAdviceCache.put(adviceBean, attrMethods);
                if (logger.isInfoEnabled()) {
                    logger.info("Detected @ModelAttribute methods in " + adviceBean);
                }
            }
            Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
            if (!binderMethods.isEmpty()) {
                this.initBinderAdviceCache.put(adviceBean, binderMethods);
                if (logger.isInfoEnabled()) {
                    logger.info("Detected @InitBinder methods in " + adviceBean);
                }
            }
            if (RequestBodyAdvice.class.isAssignableFrom(beanType)) {
                requestResponseBodyAdviceBeans.add(adviceBean);
                if (logger.isInfoEnabled()) {
                    logger.info("Detected RequestBodyAdvice bean in " + adviceBean);
                }
            }
            if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
                requestResponseBodyAdviceBeans.add(adviceBean);
                if (logger.isInfoEnabled()) {
                    logger.info("Detected ResponseBodyAdvice bean in " + adviceBean);
                }
            }
        }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值