第一,注解:
-
@Before – 目标方法执行前执行
-
@After – 目标方法执行后执行
-
@AfterReturning – 目标方法返回后执行,如果发生异常不执行
-
@AfterThrowing – 异常时执行
-
@Around – 在执行上面其他操作的同时也执行这个方法
第二,SpringMVC如果要使用AOP注解,必须将放在spring-servlet.xml(配置MVC的XML)中
< aop:aspectj-autoproxy proxy-target-class = "true" /> |
项目截图
首先是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:\t" +joinPoint.getKind()); System.out.println( "Target:\t" +joinPoint.getTarget().toString()); Object[] os=joinPoint.getArgs(); System.out.println( "Args:" ); for ( int i= 0 ;i<os.length;i++){ System.out.println( "\t==>参数[" +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<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:\t" +joinPoint.getKind()); System.out.println( "Target:\t" +joinPoint.getTarget().toString()); Object[] os=joinPoint.getArgs(); System.out.println( "Args:" ); for ( int i= 0 ;i<os.length;i++){ System.out.println( "\t==>参数[" +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()); } } |