如何在Spring Boot中通过自定义注解为方法添加指定逻辑?
解决方案:用Spring AOP实现类级注解的自动逻辑注入
要实现给标注了自定义注解的Controller类自动注入model.addAttribute("key","value")的逻辑,最直接的方案是用Spring AOP,完全不需要修改原有方法代码。以下是具体实现步骤:
1. 定义自定义类级注解
先创建你的@MyCustomAnnotation注解,指定作用于类,且运行时可被识别:
import java.lang.annotation.*; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface MyCustomAnnotation { }
2. 编写AOP切面类
通过AOP的环绕通知,拦截所有标注了@MyCustomAnnotation的类的方法,自动注入Model属性:
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; import org.springframework.ui.Model; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.servlet.ModelAndView; @Aspect @Component public class CustomAnnotationAspect { // 切点:匹配所有标注了@MyCustomAnnotation的类中的方法 @Around("@within(com.yourpackage.MyCustomAnnotation)") public Object injectModelAttribute(ProceedingJoinPoint joinPoint) throws Throwable { // 先执行原方法,拿到返回结果 Object result = joinPoint.proceed(); // 获取当前请求上下文,操作Model ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (attributes != null) { // 方式1:从方法参数里找到Model对象,添加属性 for (Object arg : joinPoint.getArgs()) { if (arg instanceof Model) { ((Model) arg).addAttribute("key", "value"); break; } } // 方式2:如果方法返回ModelAndView,直接往里面加属性 if (result instanceof ModelAndView) { ((ModelAndView) result).addObject("key", "value"); } } return result; } }
3. 给Controller标注注解
直接在你的Controller类上加上@MyCustomAnnotation,原方法完全不用改:
import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @Controller @MyCustomAnnotation public class ExController { @GetMapping("/index") public String index(Model model) { // 不用手动写model.addAttribute("key","value") return "index"; } }
核心技术关键词
- Spring AOP:无侵入式拦截方法,注入额外逻辑
- @within() 切点表达式:精准匹配标注了指定注解的类的所有方法
- ProceedingJoinPoint:控制原方法执行、获取参数和返回值的核心类
- RequestContextHolder:获取当前HTTP请求上下文,操作Model/ModelAndView
替代方案:用HandlerInterceptor拦截请求
如果只针对Controller的HTTP请求,也可以用拦截器实现:
- 编写拦截器类:
import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class CustomAnnotationInterceptor implements HandlerInterceptor { @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 判断当前请求对应的Controller是否标注了自定义注解 if (handler instanceof org.springframework.web.method.HandlerMethod) { org.springframework.web.method.HandlerMethod handlerMethod = (org.springframework.web.method.HandlerMethod) handler; Class<?> controllerClass = handlerMethod.getBeanType(); if (controllerClass.isAnnotationPresent(MyCustomAnnotation.class)) { if (modelAndView != null) { modelAndView.addObject("key", "value"); } } } } }
- 注册拦截器到Spring配置:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new CustomAnnotationInterceptor()); } }
内容的提问来源于stack exchange,提问作者terius
相关产品推荐
相关产品推荐

