zoukankan      html  css  js  c++  java
  • SpringMVC利用AOP实现自定义注解记录日志

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

    第一注解

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

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

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

    4. @AfterThrowing – 异常时执行

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

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

    <aop:aspectj-autoproxy proxy-target-class="true"/>

    放在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

    项目截图

    首先是Maven依赖

    <properties>
    		<springframework>4.0.5.RELEASE</springframework>
    		<aspectj>1.8.5</aspectj>
    		<servlet>3.1.0</servlet>
    	</properties>
    	<dependencies>
    		<!-- servlet -->
    		<dependency>
    			<groupId>javax.servlet</groupId>
    			<artifactId>javax.servlet-api</artifactId>
    			<version>${servlet}</version>
    			<scope>compile</scope>
    		</dependency>
    		<!-- Spring web mvc -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-webmvc</artifactId>
    			<version>${springframework}</version>
    		</dependency>
    		<!-- Spring AOP -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-aop</artifactId>
    			<version>${springframework}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.aspectj</groupId>
    			<artifactId>aspectjrt</artifactId>
    			<version>${aspectj}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.aspectj</groupId>
    			<artifactId>aspectjweaver</artifactId>
    			<version>${aspectj}</version>
    		</dependency>
    	</dependencies>

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

    <!-- 配置扫描路径 -->
    	<context:component-scan base-package="org.xdemo.example.springaop">
    		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    	</context:component-scan>

    spring-mvc.xml配置

    <!-- 最重要:::如果放在spring-context.xml中,这里的aop设置将不会生效 -->
        <aop:aspectj-autoproxy proxy-target-class="true"/>
    	<!-- 启用MVC注解 -->
    	<mvc:annotation-driven />
    
    	<!-- 指定Sping组件扫描的基本包路径 -->
    	<context:component-scan base-package="org.xdemo.example.springaop">
    		<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    	</context:component-scan>

    Web.xml配置

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
    	<display-name>Archetype Created Web Application</display-name>
    	<!-- WebAppRootKey -->
    	<context-param>
    		<param-name>webAppRootKey</param-name>
    		<param-value>org.xdemo.example.springaop</param-value>
    	</context-param>
    
    	<!-- Spring Context -->
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>classpath:spring-context.xml</param-value>
    	</context-param>
    	<listener>
    		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    	</listener>
    
    	<!-- SpringMVC -->
    	<servlet>
    		<servlet-name>SpringMVC</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<init-param>
    			<param-name>contextConfigLocation</param-name>
    			<param-value>classpath:spring-mvc.xml</param-value>
    		</init-param>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    	<servlet-mapping>
    		<servlet-name>SpringMVC</servlet-name>
    		<url-pattern>/</url-pattern>
    	</servlet-mapping>
    
    </web-app>

    注解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<Long> time=new ThreadLocal<Long>();
    	ThreadLocal<String> tag=new ThreadLocal<String>();
    	
    	/**
    	 * 在所有标注@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:	"+joinPoint.getKind());
    		System.out.println("Target:	"+joinPoint.getTarget().toString());
    		Object[] os=joinPoint.getArgs();
    		System.out.println("Args:");
    		for(int i=0;i<os.length;i++){
    			System.out.println("	==>参数["+i+"]:	"+os[i].toString());
    		}
    		System.out.println("Signature:	"+joinPoint.getSignature());
    		System.out.println("SourceLocation:	"+joinPoint.getSourceLocation());
    		System.out.println("StaticPart:	"+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<Long> time=new ThreadLocal<Long>();
    	ThreadLocal<String> tag=new ThreadLocal<String>();
    	
    	@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:	"+joinPoint.getKind());
    		System.out.println("Target:	"+joinPoint.getTarget().toString());
    		Object[] os=joinPoint.getArgs();
    		System.out.println("Args:");
    		for(int i=0;i<os.length;i++){
    			System.out.println("	==>参数["+i+"]:	"+os[i].toString());
    		}
    		System.out.println("Signature:	"+joinPoint.getSignature());
    		System.out.println("SourceLocation:	"+joinPoint.getSourceLocation());
    		System.out.println("StaticPart:	"+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

    结果如下:

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

  • 相关阅读:
    Sprng Data JPA与hibernate的关系
    Exception in thread "main" java.io.FileNotFoundException: d:xxx.txt (拒绝访问。)
    Telnet测试BIO Socket
    计算机网络篇
    Postman测试接口发现时间少8个小时?添加这两行代码就解决!
    匿名内部类
    解决线程安全的三种方法
    equals和hashcode的区别
    postman测试springsecurity 登录鉴权,获取Cookie后进行其他接口测试
    (链表)求相交链表交点
  • 原文地址:https://www.cnblogs.com/lxl57610/p/7485474.html
Copyright © 2011-2022 走看看