Spring-AOP之aspectj注解方式

一、简介
1、AOP用在哪些方面:AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理日志管理权限控制异常处理等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
2、AOP中的概念:
Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面是横切性关注点的抽象.
joinpoint(连接点):所谓连接点是指那些被拦截到的点(可以是方法、属性、或者类的初始化时机(可以是Action层、Service层、dao层))。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器)
Pointcut(切入点):所谓切入点是指我们要对那些joinpoint进行拦截的定义,也即joinpoint的集合.
Advice(通知):所谓通知是指拦截到joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知
Target(目标对象):代理的目标对象
Weave(织入):指将aspects应用到target对象并导致proxy对象创建的过程称为织入.
Introduction(引入):在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.

3、AOP带来的好处::降低模块的耦合度;使系统容易扩展;更好的代码复用性

二、通过注解方式实现Spring的AOP

1.定义业务类

接口:

[java]

  1. package cn.slimsmart.spring.demo.aop;

  2. public interface UserService {

  3. String save(String name);

  4. String update(String name);

  5. String delete(String name);

  6. }

实现:

[java]

  1. package cn.slimsmart.spring.demo.aop;

  2. import org.springframework.stereotype.Service;

  3. @Service <span style="font-family: Arial, Helvetica, sans-serif;">//使用自动注解的方式实例化并初始化该类</span>

  4. public class UserServiceImpl implements UserService{

  5. @Override

  6. public String save(String name) {

  7. System.out.println("--------save");

  8. return "save";

  9. }

  10. @Override

  11. public String update(String name) {

  12. System.out.println("--------update");

  13. System.out.println(1/0);

  14. return "update";

  15. }

  16. @Override

  17. public String delete(String name) {

  18. System.out.println("--------delete");

  19. return "delete";

  20. }

  21. }

2.定义切面类

[java]

  1. package cn.slimsmart.spring.demo.aop;

  2. import org.aspectj.lang.JoinPoint;

  3. import org.aspectj.lang.ProceedingJoinPoint;

  4. import org.aspectj.lang.annotation.After;

  5. import org.aspectj.lang.annotation.AfterReturning;

  6. import org.aspectj.lang.annotation.AfterThrowing;

  7. import org.aspectj.lang.annotation.Around;

  8. import org.aspectj.lang.annotation.Aspect;

  9. import org.aspectj.lang.annotation.Before;

  10. import org.aspectj.lang.annotation.Pointcut;

  11. import org.springframework.stereotype.Component;

  12. //@Aspect : 标记为切面类

  13. //@Pointcut : 指定匹配切点集合

  14. //@Before : 指定前置通知,value中指定切入点匹配

  15. //@AfterReturning :后置通知,具有可以指定返回值

  16. //@AfterThrowing :异常通知

  17. //@Around 环绕通知 环绕通知的方法中一定要有ProceedingJoinPoint 参数,与Filter中的 doFilter方法类似

  18. //注意:前置/后置/异常通知的函数都没有返回值,只有环绕通知有返回值

  19. @Component //使用自动注解的方式实例化并初始化该类

  20. @Aspect

  21. public class TestInterceptor {

  22. //如果要设置多个切点可以使用 || 拼接

  23. @Pointcut("execution(* cn.slimsmart.spring.demo.aop.UserServiceImpl.*(..))")

  24. private void anyMethod() {

  25. }// 定义一个切入点

  26. @Before(value="anyMethod()")

  27. public void doBefore(JoinPoint joinPoint) {

  28. System.out.println("前置通知");

  29. }

  30. @AfterReturning(value="anyMethod()",returning="result")

  31. public void doAfter(JoinPoint jp, String result) {

  32. System.out.println("后置通知");

  33. }

  34. @After("anyMethod()")

  35. public void after() {

  36. System.out.println("最终通知");

  37. }

  38. @AfterThrowing(value="execution(* cn.slimsmart.spring.demo.aop.*.*(..))",throwing="e")

  39. public void doAfterThrow(JoinPoint joinPoint, Throwable e) {

  40. System.out.println("异常通知");

  41. }

  42. @Around("execution(* cn.slimsmart.spring.demo.aop.*.*(..))")

  43. public Object doBasicProfiling(ProceedingJoinPoint joinPoint) throws Throwable {

  44. System.out.println("进入环绕通知");

  45. System.out.println("目标类名称:"+joinPoint.getTarget().getClass().getName());

  46. System.out.println("方法名称:"+joinPoint.getSignature().getName());

  47. System.out.println("方法参数:"+joinPoint.getArgs());

  48. System.out.println("staticPart:"+ joinPoint.getStaticPart().toShortString());

  49. System.out.println("kind:"+joinPoint.getKind());

  50. System.out.println("sourceLocation:"+joinPoint.getSourceLocation());

  51. Object object = joinPoint.proceed();// 执行该方法

  52. System.out.println("退出方法");

  53. return object;

  54. }

  55. }

3.applicationContext.xml配置

[html]

  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <beans xmlns="http://www.springframework.org/schema/beans"

  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  4. xmlns:context="http://www.springframework.org/schema/context"

  5. xmlns:aop="http://www.springframework.org/schema/aop"

  6. xmlns:tx="http://www.springframework.org/schema/tx"

  7. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd

  8. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd

  9. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd

  10. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

  11. <context:component-scan base-package="cn.slimsmart.spring.demo" />

  12. <!-- 打开aop 注解 -->

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

  14. </beans>

4.单元测试类

[java]

  1. package cn.slimsmart.spring.demo;

  2. import org.junit.Test;

  3. import org.junit.runner.RunWith;

  4. import org.springframework.beans.factory.annotation.Autowired;

  5. import org.springframework.test.context.ContextConfiguration;

  6. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

  7. import cn.slimsmart.spring.demo.aop.UserService;

  8. @RunWith(SpringJUnit4ClassRunner.class)//让junit工作在spring环境中

  9. @ContextConfiguration(locations={"classpath:applicationContext.xml"})

  10. public class SpringTest{

  11. @Autowired

  12. UserService userService;

  13. @Test

  14. public void testStart(){

  15. System.out.println("启动服务");

  16. userService.delete("abc123");

  17. System.out.println("====================");

  18. userService.update("aaa");

  19. }

  20. }


运行结果:执行update抛异常:/ by zero

[plain]

  1. 启动服务

  2. 进入环绕通知

  3. 目标类名称:cn.slimsmart.spring.demo.aop.UserServiceImpl

  4. 方法名称:delete

  5. 方法参数:[Ljava.lang.Object;@2de1c3f9

  6. staticPart:execution(UserServiceImpl.delete(..))

  7. kind:method-execution

  8. sourceLocation:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@6ed745c2

  9. 前置通知

  10. --------delete

  11. 退出方法

  12. 最终通知

  13. 后置通知

  14. ====================

  15. 进入环绕通知

  16. 目标类名称:cn.slimsmart.spring.demo.aop.UserServiceImpl

  17. 方法名称:update

  18. 方法参数:[Ljava.lang.Object;@1d370b4d

  19. staticPart:execution(UserServiceImpl.update(..))

  20. kind:method-execution

  21. sourceLocation:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@8c6fb37

  22. 前置通知

  23. --------update

  24. 最终通知

  25. 异常通知

注:pom.xml引入的jar包

[html]

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  3. <modelVersion>4.0.0</modelVersion>

  4. <groupId>cn.slimsmart.spring.demo</groupId>

  5. <artifactId>spring-demo</artifactId>

  6. <version>0.0.1-SNAPSHOT</version>

  7. <dependencies>

  8. <dependency>

  9. <groupId>org.springframework</groupId>

  10. <artifactId>spring-context</artifactId>

  11. <version>4.1.4.RELEASE</version>

  12. </dependency>

  13. <!-- <dependency> -->

  14. <!-- <groupId>org.springframework</groupId> -->

  15. <!-- <artifactId>spring-tx</artifactId> -->

  16. <!-- <version>4.1.4.RELEASE</version> -->

  17. <!-- </dependency> -->

  18. <!-- <dependency> -->

  19. <!-- <groupId>org.springframework</groupId> -->

  20. <!-- <artifactId>spring-jdbc</artifactId> -->

  21. <!-- <version>4.1.4.RELEASE</version> -->

  22. <!-- </dependency> -->

  23. <dependency>

  24. <groupId>org.springframework</groupId>

  25. <artifactId>spring-test</artifactId>

  26. <version>4.1.4.RELEASE</version>

  27. </dependency>

  28. <dependency>

  29. <groupId>aspectj</groupId>

  30. <artifactId>aspectjrt</artifactId>

  31. <version>1.5.4</version>

  32. </dependency>

  33. <dependency>

  34. <groupId>org.aspectj</groupId>

  35. <artifactId>aspectjweaver</artifactId>

  36. <version>1.8.4</version>

  37. </dependency>

  38. <dependency>

  39. <groupId>cglib</groupId>

  40. <artifactId>cglib</artifactId>

  41. <version>3.1</version>

  42. </dependency>

  43. <dependency>

  44. <groupId>cglib</groupId>

  45. <artifactId>cglib-nodep</artifactId>

  46. <version>3.1</version>

  47. </dependency>

  48. <dependency>

  49. <groupId>junit</groupId>

  50. <artifactId>junit</artifactId>

  51. <version>4.12</version>

  52. </dependency>

  53. </dependencies>

  54. </project>

若不使用注解的方式,使用schema xml配置(也可以基于spring接口方式实现)的方式,如下参考:

[html]

  1. <aop:config>

  2. <aop:aspect id="businessAspect" ref="testInterceptor">

  3. <!-- 配置指定切入的对象 -->

  4. <aop:pointcut id="point_cut" expression="execution(* cn.slimsmart.spring.demo.aop.UserServiceImpl.*(..))" />

  5. <!-- 前置通知 -->

  6. <aop:before method="doBefore" pointcut-ref="point_cut" />

  7. <!-- 后置通知 returning指定返回参数 -->

  8. <aop:after-returning method="doAfter"

  9. pointcut-ref="point_cut" returning="result" />

  10. <aop:around method="doAround" pointcut-ref="point_cut"/>

  11. <aop:after-throwing method="doThrow" pointcut-ref="point_cut" throwing="e"/>

  12. </aop:aspect>

  13. </aop:config>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值