在方法执行的前后,切入代码;经典的service层切入事务;



@Aspect注解是切面注解类
@Pointcut切点定义
@Before是方法执行前调用
@After是方法执行后调用
@AfterReturning方法执行返回值调用



Service层本身就可以切入事务,所以我们这类搞个常用的 切controller层方法

每个执行controller层的方法 都记录下请求Url,访问者IP 执行类方法参数等信息;

 

紧接上一讲,这里只是多了切面类,项目结构:

spring boot 自定义注解 + AOP切面 (切面不生效) springboot切面类_java

贴下代码:

1.切面类com.cy.aspect.RequestAspect.java:



package com.cy.aspect;

import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.cy.entity.Student;
import ch.qos.logback.classic.Logger;

/**
 * 切面类
 */
@Aspect
@Component
public class RequestAspect {
    
    private Logger logger= (Logger) LoggerFactory.getLogger(RequestAspect.class);
    
    /**
     * Pointcut定义切点
     * public修饰符的   返回值任意  com.cy.controller包下面的任意类的任意方法任意参数
     */
    @Pointcut("execution(public * com.cy.controller.*.*(..))")
    public void log(){
        
    }
    
    @Before("log()")
    public void doBefore(JoinPoint joinPoint){
        logger.info("方法执行前...");
        ServletRequestAttributes sra =  (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sra.getRequest();
        logger.info("url: " + request.getRequestURI());  //url
        logger.info("ip: " + request.getRemoteHost());   //ip
        logger.info("method: "+request.getMethod());      //post or get? or ?
        logger.info("class.method: " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); 
        logger.info("args: "+joinPoint.getArgs());
        Student student = (Student) joinPoint.getArgs()[0];
        logger.info(student.toString());
    }
    
    @After("log()")
    public void doAfter(JoinPoint joinPoint){
        logger.info("方法执行后...");
    }
    
    @AfterReturning(returning="result", pointcut="log()")
    public void doAfterReturnint(Object result){
        logger.info("方法返回值:" + result);
    }
}



回顾前一章的StudentController是这样的:



/**
     * 添加学生
     * @param student
     * @return
     */
    @RequestMapping("/add")
    public String add(@Valid Student student, BindingResult bindingResult){
        if(bindingResult.hasErrors()){
            return bindingResult.getFieldError().getDefaultMessage();
        }else{
            studentService.add(student);
            return "添加成功";
        }
    }



 

测试:



2018-03-25 16:34:53.984  INFO 3744 --- [p-nio-80-exec-1] com.cy.aspect.RequestAspect              : 方法执行前...
2018-03-25 16:34:53.984  INFO 3744 --- [p-nio-80-exec-1] com.cy.aspect.RequestAspect              : url: /student/add
2018-03-25 16:34:53.984  INFO 3744 --- [p-nio-80-exec-1] com.cy.aspect.RequestAspect              : ip: 0:0:0:0:0:0:0:1
2018-03-25 16:34:53.984  INFO 3744 --- [p-nio-80-exec-1] com.cy.aspect.RequestAspect              : method: POST
2018-03-25 16:34:53.986  INFO 3744 --- [p-nio-80-exec-1] com.cy.aspect.RequestAspect              : class.method: com.cy.controller.StudentController.add
2018-03-25 16:34:53.986  INFO 3744 --- [p-nio-80-exec-1] com.cy.aspect.RequestAspect              : args: [Ljava.lang.Object;@4232f676
2018-03-25 16:34:53.986  INFO 3744 --- [p-nio-80-exec-1] com.cy.aspect.RequestAspect              : Student [id=null, name=余学海, age=28]
Hibernate: select next_val as id_val from hibernate_sequence for update
Hibernate: update hibernate_sequence set next_val= ? where next_val=?
Hibernate: insert into t_student (age, name, id) values (?, ?, ?)
2018-03-25 16:34:54.067  INFO 3744 --- [p-nio-80-exec-1] com.cy.aspect.RequestAspect              : 方法执行后...
2018-03-25 16:34:54.067  INFO 3744 --- [p-nio-80-exec-1] com.cy.aspect.RequestAspect              : 方法返回值:添加成功