SpringAop @Aspect织入不生效,不执行前置增强织入@Before方式

目录
  • SpringAop @Aspect织入不生效,不执行前置增强织入@Before
    • 想写一个AOP,主要有2个用意
  • 使用@Aspect,@Before不被调用

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

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • SpringMVC记录我遇到的坑_AOP注解无效,切面不执行的解决

    AOP注解无效,切面不执行的解决 想做一个api请求日志,想到使用aop,配置过程中遇到了一个坑,aop不起作用, 我的aop是这样的: package com.ljwm.ibei.aspact; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.l

  • 详解spring中aop不生效的几种解决办法

    先看下这个问题的背景:假设有一个spring应用,开发人员希望自定义一个注解@Log,可以加到指定的方法上,实现自动记录日志(入参.出参.响应耗时这些) package com.cnblogs.yjmyzz.springbootdemo.aspect; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy

  • Spring AOP定义Before增加实战案例详解

    本文实例讲述了Spring AOP定义Before增加.分享给大家供大家参考,具体如下: 一 配置 <?xml version="1.0" encoding="GBK"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:

  • Spring aop失效的几种解决方案

    先看下这个问题的背景:假设有一个spring应用,开发人员希望自定义一个注解@Log,可以加到指定的方法上,实现自动记录日志(入参.出参.响应耗时这些) package com.cnblogs.yjmyzz.springbootdemo.aspect; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy

  • SpringAop @Aspect织入不生效,不执行前置增强织入@Before方式

    目录 SpringAop @Aspect织入不生效,不执行前置增强织入@Before 想写一个AOP,主要有2个用意 使用@Aspect,@Before不被调用 SpringAop @Aspect织入不生效,不执行前置增强织入@Before 想写一个AOP,主要有2个用意 第一个用意是做后端的防表单重复提交的token验证. 第二个用意是对后台JSR303 Validator的校验结果做一个统一处理,不想把对校验结果的处理分散在每个controller方法中 @ResponseBody @Req

  • SpringBoot启动时自动执行代码的几种实现方式

    目录 前言 java自身的启动时加载方式 static代码块 构造方法 Spring启动时加载方式 代码测试 总结 前言 目前开发的SpringBoot项目在启动的时候需要预加载一些资源.而如何实现启动过程中执行代码,或启动成功后执行,是有很多种方式可以选择,我们可以在static代码块中实现,也可以在构造方法里实现,也可以使用@PostConstruct注解实现. 当然也可以去实现Spring的ApplicationRunner与CommandLineRunner接口去实现启动后运行的功能.在

  • 通过T_sql语句向其中一次填入一条数据或一次填入多条数据的方式填充数据

    使用T_SQL创建数据库 TestSchool 创建一个学生表 TblStudent 创建学生成绩表 TblScore q tScoreId (成绩 id, 主键 , 自动编号). tSId (学生编号). tEnglish (英语成绩). tMath (数学成绩) 创建老师表 TblTeacher q tTId . tTName . tTGender . tTAge . tTSalary . tTBirthday 并使用T_sql语句向其中一次填入一条数据或一次填入多条数据的方式填入数据. (

  • spyder 在控制台(console)执行python文件,debug python程序方式

    执行: 在IPython console里先cd到test.py所在的文件夹,再run test.py.注意使用的是命令run 而不是命令python. debug: 栗子: debugfile('/home/1/tensor2tensor/tensor2tensor/bin/t2t-datagen', args='--problem=image_mnist --data_dir=~/t2t_data --tmp_dir=~/t2t_data/tmp',wdir='/home/1/tensor2

  • python 轮询执行某函数的2种方式

    目标:python中每隔特定时间执行某函数 方法1:使用python的Thread类的子类Timer,该子类可控制指定函数在特定时间后执行一次: 所以为了实现多次定时执行某函数,只需要在一个while循环中多次新建Timer即可. from threading import Timer import time def printHello(): print ("Hello") print("当前时间戳是", time.time()) def loop_func(fu

  • 详解Java执行groovy脚本的两种方式

    记录Java执行groovy脚本的两种方式,简单粗暴: 一种是通过脚本引擎ScriptEngine提供的eval(String)方法执行脚本内容:一种是执行groovy脚本: 二者都通过Invocable来传递参数并获取执行结果: Invocable:脚本引擎的解释器接口,提供invokeFunction和invokeMethod两种传递参数并获取执行结果的方法,Java JDK API文档解释如下: invokeFunction: invokeMethod: 以下为案例: 引入依赖 <depe

  • Spring Boot 项目启动自动执行方法的两种实现方式

    目录 实际应用场景: 第一种实现ApplicationRunner接口 第二种实现CommandLineRunner接口 对比: 注意: 实际应用场景: springboot项目启动成功后执行一段代码,如系统常量,配置.代码集等等初始化操作:执行多个方法时,执行顺序使用Order注解或Order接口来控制. Springboot给我们提供了两种方式 第一种实现ApplicationRunner接口 package org.mundo.demo.core; import org.springfra

  • js执行shell命令的几种方式(Node)

    目录 前言 调起shell的几种方式介绍(不限于这几种) 1.child_process 2.shelljs 3.simple-git 总结 在做一个客户端基建项目的时候,多处需要用到JS调取命令行执行shell脚本,这里对shell命令.JS执行shell命令做一个简单的介绍和总结. 前言 一般在纯前端静态页面的项目中,是不需要JS调命令行操作的,通常在Node项目,或者在Electron客户端项目中,可能会有这样的需求.(electron这个客户端框架本身就内置了node的很多方法).因此下

  • Oracle执行Update语句的几种方式

    Oracle没有update from语法,可以通过四种写法实现同样的功能: 一.标准update语法(常用.速度可能最慢) 当更新的表示单个或者被更新的字段不需要关联表带过来,此法是最好的选择. update a set a.c2= (select b.c2from b where a.c1=b.c1) where exists (select 1 from b where a.c1=b.c1) 二.内联视图更新(关联主键字段,速度较快) inline view更新法就是更新一个临时建立的视图

  • 关于命令行执行Python脚本的传参方式

    目录 命令行执行Python脚本的传参 应用场景 方式一 方式二 python-命令行传参sys.argv实际运用 argv获取参数 getopt模块 实例 实际场景运用 命令行执行Python脚本的传参 应用场景 在对ABAQUS进行二次开发时,需要将核心脚本的外部数据传递到脚本内部并执行 核心脚本在运行时,可以调用所传递的变量参数 命令行执行或者用户子程序执行 方式一 使用sys.args 简单示例 import sys def test_sys_args():     if len(sys

随机推荐