SpringMVC利用AOP实现自定义注解记录日志

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

转载请注明来源:http://www.xdemo.org/springmvc-aop-annotation/

其他参考:

http://www.importnew.com/13367.html

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html

http://dove19900520.iteye.com/blog/2289806

http://jinnianshilongnian.iteye.com/blog/1670856

 

本文抛砖引玉,并没有详细的介绍更全面的内容,通过一个例子让初次使用的人能够快速入门,简单的介绍一下。

第一,注解:

  1. @Before – 目标方法执行前执行

  2. @After – 目标方法执行后执行

  3. @AfterReturning – 目标方法返回后执行,如果发生异常不执行

  4. @AfterThrowing – 异常时执行

  5. @Around – 在执行上面其他操作的同时也执行这个方法

第二,SpringMVC如果要使用AOP注解,必须将

放在spring-servlet.xml(配置MVC的XML)中

第三,execution表达式请参考Spring官网http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html

代码下载:http://pan.baidu.com/s/1gdeopW3

项目截图

SpringMVC利用AOP实现自定义注解记录日志_第1张图片

 

首先是Maven依赖


        4.0.5.RELEASE
        1.8.5
        3.1.0
    
    
        
        
            javax.servlet
            javax.servlet-api
            ${servlet}
            compile
        
        
        
            org.springframework
            spring-webmvc
            ${springframework}
        
        
        
            org.springframework
            spring-aop
            ${springframework}
        
        
            org.aspectj
            aspectjrt
            ${aspectj}
        
        
            org.aspectj
            aspectjweaver
            ${aspectj}
        
    

spring-context.xml配置,基本无内容

!-- 配置扫描路径 -->
    
        
    

spring-mvc.xml配置


    
    
    
 
    
    
        
    

Web.xml配置



    Archetype Created Web Application
    
    
        webAppRootKey
        org.xdemo.example.springaop
    
 
    
    
        contextConfigLocation
        classpath:spring-context.xml
    
    
        org.springframework.web.context.ContextLoaderListener
    
 
    
    
        SpringMVC
        org.springframework.web.servlet.DispatcherServlet
        
            contextConfigLocation
            classpath:spring-mvc.xml
        
        1
    
    
        SpringMVC
        /
    
 

注解Log

package org.xdemo.example.springaop.annotation;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface Log {
    String name() default "";
}

日志AOP,写法一LogAop_1

package org.xdemo.example.springaop.aop;
 
import java.lang.reflect.Method;
import java.util.UUID;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.xdemo.example.springaop.annotation.Log;
 
@Aspect
@Component
public class LogAop_1 {
 
    ThreadLocal time=new ThreadLocal();
    ThreadLocal tag=new ThreadLocal();
     
    /**
     * 在所有标注@Log的地方切入
     * @param joinPoint
     */
    @Before("@annotation(org.xdemo.example.springaop.annotation.Log)")
    public void beforeExec(JoinPoint joinPoint){
         
        time.set(System.currentTimeMillis());
        tag.set(UUID.randomUUID().toString());
         
        info(joinPoint);
         
        MethodSignature ms=(MethodSignature) joinPoint.getSignature();
        Method method=ms.getMethod();
        System.out.println(method.getAnnotation(Log.class).name()+"标记"+tag.get());
    }
     
    @After("@annotation(org.xdemo.example.springaop.annotation.Log)")
    public void afterExec(JoinPoint joinPoint){
        MethodSignature ms=(MethodSignature) joinPoint.getSignature();
        Method method=ms.getMethod();
        System.out.println("标记为"+tag.get()+"的方法"+method.getName()+"运行消耗"+(System.currentTimeMillis()-time.get())+"ms");
    }
     
    @Around("@annotation(org.xdemo.example.springaop.annotation.Log)")
    public void aroundExec(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("我是Around,来打酱油的");
        pjp.proceed();
    }
     
    private void info(JoinPoint joinPoint){
        System.out.println("--------------------------------------------------");
        System.out.println("King:\t"+joinPoint.getKind());
        System.out.println("Target:\t"+joinPoint.getTarget().toString());
        Object[] os=joinPoint.getArgs();
        System.out.println("Args:");
        for(int i=0;i参数["+i+"]:\t"+os[i].toString());
        }
        System.out.println("Signature:\t"+joinPoint.getSignature());
        System.out.println("SourceLocation:\t"+joinPoint.getSourceLocation());
        System.out.println("StaticPart:\t"+joinPoint.getStaticPart());
        System.out.println("--------------------------------------------------");
    }
     
     
}

日志AOP,写法二LogAop_2

package org.xdemo.example.springaop.aop;
 
import java.lang.reflect.Method;
import java.util.UUID;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.xdemo.example.springaop.annotation.Log;
 
@Aspect
@Component
public class LogAop_2 {
 
    ThreadLocal time=new ThreadLocal();
    ThreadLocal tag=new ThreadLocal();
     
    @Pointcut("@annotation(org.xdemo.example.springaop.annotation.Log)")
    public void log(){
        System.out.println("我是一个切入点");
    }
     
    /**
     * 在所有标注@Log的地方切入
     * @param joinPoint
     */
    @Before("log()")
    public void beforeExec(JoinPoint joinPoint){
         
        time.set(System.currentTimeMillis());
        tag.set(UUID.randomUUID().toString());
         
        info(joinPoint);
         
        MethodSignature ms=(MethodSignature) joinPoint.getSignature();
        Method method=ms.getMethod();
        System.out.println(method.getAnnotation(Log.class).name()+"标记"+tag.get());
    }
     
    @After("log()")
    public void afterExec(JoinPoint joinPoint){
        MethodSignature ms=(MethodSignature) joinPoint.getSignature();
        Method method=ms.getMethod();
        System.out.println("标记为"+tag.get()+"的方法"+method.getName()+"运行消耗"+(System.currentTimeMillis()-time.get())+"ms");
    }
     
    @Around("log()")
    public void aroundExec(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("我是Around,来打酱油的");
        pjp.proceed();
    }
     
    private void info(JoinPoint joinPoint){
        System.out.println("--------------------------------------------------");
        System.out.println("King:\t"+joinPoint.getKind());
        System.out.println("Target:\t"+joinPoint.getTarget().toString());
        Object[] os=joinPoint.getArgs();
        System.out.println("Args:");
        for(int i=0;i参数["+i+"]:\t"+os[i].toString());
        }
        System.out.println("Signature:\t"+joinPoint.getSignature());
        System.out.println("SourceLocation:\t"+joinPoint.getSourceLocation());
        System.out.println("StaticPart:\t"+joinPoint.getStaticPart());
        System.out.println("--------------------------------------------------");
    }
     
}

用到的一个用户类User

package org.xdemo.example.springaop.bean;
 
public class User {
 
    private String name;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
}

一个测试的Controller

package org.xdemo.example.springaop.controller;
 
import javax.annotation.Resource;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.xdemo.example.springaop.annotation.Log;
import org.xdemo.example.springaop.bean.User;
import org.xdemo.example.springaop.service.IUserService;
 
 
@Controller
@RequestMapping("/aop")
public class SpringController {
     
    @Resource IUserService userService;
     
    @Log(name="您访问了aop1方法")
    @ResponseBody
    @RequestMapping(value="aop1")
    public String aop1(){
        return "AOP";
    }
     
    @Log(name="您访问了aop2方法")
    @ResponseBody
    @RequestMapping(value="aop2")
    public String aop2(String string) throws InterruptedException{
        Thread.sleep(1000L);
        User user=new User();
        user.setName(string);
        userService.save(user);
        return string;
    }
     
}

一个测试的接口实现类(接口类略)

package org.xdemo.example.springaop.service;
 
import org.springframework.stereotype.Service;
import org.xdemo.example.springaop.annotation.Log;
import org.xdemo.example.springaop.bean.User;
 
@Service
public class UserServiceImpl implements IUserService {
 
    @Log(name = "您访问了保存用户信息")
    public void save(User user) {
        System.out.println(user.getName());
    }
 
}

在地址栏输入地址测试

http://localhost:8080/springaop/aop/aop2?string=sxxxxx

结果如下

SpringMVC利用AOP实现自定义注解记录日志_第2张图片

转载请注明来源:http://www.xdemo.org/springmvc-aop-annotation/

转载于:https://my.oschina.net/runforfuture/blog/756192

你可能感兴趣的:(SpringMVC利用AOP实现自定义注解记录日志)