SpringAop @Aspect织入不生效,不执行前置增强织入@Before方式
作者:苦作舟 时间:2021-09-18 04:00:58
SpringAop @Aspect织入不生效,不执行前置增强织入@Before
想写一个AOP,主要有2个用意
第一个用意是做后端的防表单重复提交的token验证。
第二个用意是对后台JSR303 Validator的校验结果做一个统一处理,不想把对校验结果的处理分散在每个controller方法中
@ResponseBody
@RequestMapping(value = "add", method = RequestMethod.POST)
public ResponseModel add(@Valid User user, BindingResult br, HttpServletResponse response) {
if(br.hasErrors()) {
return ResponseModel.validFail(getErrorsSplitNewLine(br));
}
accountService.addUser(user);
return ResponseModel.success("保存用户成功");
}
如上面方法中, br.hasErrors() 在每个表单提交方法中都存在,想单独抽出来使用AOP统一处理。
所以写一个AOP,如下:
@Aspect
@Component
public class ParamValidAspect {
@Before("@annotation(com.hebao.tech.adm.framework.annotation.ParamValid)")
public void paramValid(JoinPoint point) {
System.out.println("参数校验切入方法被调用了.....");
//省略
}
}
由于这篇文章主要是记录AOP不生效的原因,所以,这里不写具体实现了。
上面的内容定义一个Aop织入,在有注解@ParamValid的注释Controller方法上织入。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ParamValid {
}
这个ParamValid的内容,仅仅是一个标志性的注解,声明为方法层的注解,并且是运行时注解。
最后在application.xml中加入AOP * 设置。
<!-- 这个配置要配置在component-scan以后 -->
<aop:aspectj-autoproxy proxy-target-class="true" />
如果spring配置文件没引入过aop的配置,还需要在加入xml声明
大功告成,测试了一下,发现有点悲剧,根本织入不生效,也不报错,,楞是不执行相关的织入代码。
最后在网上搜了一下,发现Spring与SpringMVC是2个不同的父子容器, @Aspect如果被spring容器加载的话,而@Controller注解的这些类的实例化以及注入却是由SpringMVC来完成。 @Aspect如果被spring容器加载的时候,可能Spring MVC容器还未初始化, Controller类还未初始化,所以无法正常织入。。
所以调整如下:
@Aspect
public class ParamValidAspect {
@Before("@annotation(com.hebao.tech.adm.framework.annotation.ParamValid)")
public void paramValid(JoinPoint point) {
System.out.println("参数校验切入方法被调用了.....");
//省略
}
}
去掉@Component注解,然后把 aop:aspectj-autoproxy 移入springmvc配置文件中,并定义bean,如下:
<!-- 这个配置一定要配置在component-scan以后 -->
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="paramValidAspect" class="com.hebao.tech.adm.framework.spring.aop.ParamValidAspect"/>
这样就大功告成了。
使用@Aspect,@Before不被调用
@Aspect
@Component
public class LogAspect {
@Before("pointcut()")
public void before(){
System.out.println("before");
}
@Pointcut("@annotation(com.demo.annotation.Log)")
public void pointcut(){
}
@Around("pointcut()")
public void around(){
System.out.println("arount");
}
@After("pointcut()")
public void after(){
System.out.println("after");
}
}
调用方法返回结果:
arount
after
@Aspect
@Component
public class LogAspect {
@Before("pointcut()")
public void before(){
System.out.println("before");
}
@Pointcut("@annotation(com.mxy.annotation.Log)")
public void pointcut(){
}
@Around("pointcut()")
public void around(ProceedingJoinPoint point){
System.out.println("arount before");
try {
point.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("arount after");
}
@After("pointcut()")
public void after(){
System.out.println("after");
}
}
调用返回结果:
arount before
before
arount after
after
来源:https://blog.csdn.net/oKuZuoZhou/article/details/81015310