SpringAOP的运用方式——注解方式和XML配置方式java
AOP(Aspect Oriented Programming):面向切面编程,经过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。web
package controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping public class ProjectController { @RequestMapping("/success/{param}") public String goContent(@PathVariable String param, Model model){ System.out.println(param + "调用了 Controller"); model.addAttribute("userName",param); return "/success"; } }
package north; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; import java.io.IOException; @Configuration @EnableAspectJAutoProxy @ComponentScan(basePackages = "controller") @Aspect public class AspectStyleNorth { @Pointcut("execution(* controller.*.*(..))") public void pointcut() { System.out.println("定义切点....."); } @Before(value="pointcut()") public void before() { System.out.println("AspectStyleNorth.before()方法执行前执行....."); } @After("pointcut()") public void after(JoinPoint joinPoint) throws IOException { System.out.println("AspectStyleNorth.after()方法执行后执行....."); } @Around(value="pointcut()") public Object around(ProceedingJoinPoint pjp){ System.out.println("AspectStyleNorth.around()方法环绕start....."); Object rs = new Object(); try { rs = pjp.proceed(); } catch (Throwable e) { e.printStackTrace(); } System.out.println("AspectStyleNorth.around()方法环绕end....."); return rs; } @AfterThrowing(value="pointcut()", throwing="e") public void exception(Exception e) { //记录异常 System.out.println("exception ["+e+"]"); } }
c.springmvc.xml中须要配置对 注解类的扫描spring
<context:component-scan base-package="north"></context:component-scan>
d.效果express
【说明】:around()与before() 开始执行的前后不肯定,但before() 一定在around()中 proceedingJoinPoint.proceed()以前执行。编程
package controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping public class ProjectController { @RequestMapping("/success/{param}") public String goContent(@PathVariable String param, Model model){ System.out.println(param + "调用了 Controller"); model.addAttribute("userName",param); return "/success"; } }
<!-- 扫描下方切面配置的各个切点所在的包 --> <context:component-scan base-package="controller"></context:component-scan> <!-- 切面配置 --> <aop:config> <aop:pointcut id="pointcut" expression="execution(* controller.*.*(..))"/> <aop:aspect ref="aspectStyleSouth"> <aop:before pointcut-ref="pointcut" method="before"/> <aop:after pointcut-ref="pointcut" method="after"/> <aop:around pointcut-ref="pointcut" method="around"/> <aop:after-throwing pointcut-ref="pointcut" method="exception" throwing="e"/> </aop:aspect> </aop:config> <bean id="aspectStyleSouth" class="south.AspectStyleSouth"/>
【注】:须要同时扫描两个地方的包:①AOP附加处理逻辑所在的包;②运用到 AOP 的业务逻辑所在的包。安全
package south; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import java.io.IOException; @Aspect public class AspectStyleSouth { public void before() { System.out.println("before方法执行前执行....."); } @Pointcut("execution(* server.*.*(..))") public void pointcutA() { System.out.println("定义切点....."); } @Before(value="pointcutA()") public void beforeA() { System.out.println("AspectStyleNorth.before()方法执行前执行....."); } /** * * @Title:doAfterInServiceLayer * @Description: 方法调用后触发 * 记录结束时间 * @author shaojian.yu * @date 2014年11月2日 下午4:46:21 * @param joinPoint */ public void after(JoinPoint joinPoint) throws IOException { Object[] args = joinPoint.getArgs() == null ? new String[]{""} : joinPoint.getArgs(); System.out.println("after方法执行后执行....."+args[0]); } public Object around(ProceedingJoinPoint pjp){ System.out.println("around方法环绕start....."); Object rs = new Object(); try { rs = pjp.proceed(); } catch (Throwable e) { e.printStackTrace(); } System.out.println("around方法环绕end....."); return rs; } public void exception(Exception e) { //记录异常 System.out.println("exception ["+e+"]"); } }
d.效果mvc
项目的目录:app
延伸:ide
1.在AOP中,须要用到传参的时,可参考:【第六章】 AOP 之 6.3 基于Schema的AOP ——跟我学spring3性能
2.AOP中,方法、路径、参数等匹配的表达式,可参考:Aspectj execution表达式