学习Spring5必知必会(5)~Spring AOP



一、学习 AOP 思想的准备工作:

1、横切面关注点

在开发中,为了给业务方法中增加日志记录,权限检查,事务控制等功能,此时我们需要在修改业务方法内添加这些零散的功能代码(横切面关注点)。

  • 这些零散存在于业务方法中的功能代码【例如:日志记录,权限检查,事务控制】,我们称之为横切面关注点

    横切面关注点不属于业务范围,应该 从业务代码中剥离出来.

图片.png



2、AOP思想 (Aspect Oritention Programming):面向切面编程的思想

  • 切面:把一个个的横切关注点放到某个模块中去,称之为切面。

  • 那么每一个的切面都能影响业务的某一种功能, 切面的目的就是功能增强

    如日志切面就是一个横切关注点,应用中许多方法需要做日志记录的只需要插入日志的切面即可.

图片.png



3、AOP 思想的原理:是动态代理



4、了解 AOP 术语:

  • Joinpoint:连接点,被拦截到需要被增强的方法

         where:去哪里做增强
    
  • Pointcut:切入点,哪些包中的哪些类中的哪些方法,可认为是连接点的集合。

         where:去哪些地方做增强 
    
  • Advice增强(通知),当拦截到 Joinpoint 之后,在方法执行的什么时机(when)做什么样(what)的增强

        根据时机分为:前置增强、后置增强、异常增强、最终增强、环绕增强 
    
  • Aspect切面,Pointcut+Advice,

      去哪些地方+在什么时机+做什么增强
    


  • Target:目标对象,被代理的目标对象,委托对象。

  • Weaving:织入,把 Advice 加到 Target 上之后,创建出 Proxy 对象的过程。

  • Proxy:一个类被 AOP 织入增强后,产生的代理类 Advice(增强)执行时机,代理对象。



5、Pointcot 语法 【找到具体的某个方法-哪个包.哪个类.哪个方法

(1)AspectJ 切入点语法如下(表示在哪些包下的哪些类中的哪些方法上做切入增强):

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)

即 ★execution(<修饰符>? <返回类型> <声明类型>? <方法名>(<参数>) <异常>)


  • 例子:public static Class java.lang.Class.forName(String className)throws ClassNotFoundException


(2)切入点表达式中的通配符(看具体的方法,先从方法名位置开始看):

*:匹配任何部分,但是只能表示一个单词。

..:可用于全限定名中和方法参数中,分别**表示子包和 0 到 N 个参数**。 




二、AOP 开发:

1、依赖:

  • spring-aop.jar
  • com.springsource.org.aopalliance.jar [spring5的spring-aop.jar已经包含]
  • com.springsource.org.aspectj.weaver.jar



2、配置:

(1)引入AOP的约束(在beans的基础进行修改即可)

  • 当然也可以使用插件sts,打开xml文件方式选择 Spring Config Editor
图片.png


(2)配置AOP:

    <!-- AOP 配置:在什么地点、什么时机、做什么 -->
    <!-- 1、what【what(人物)】:做什么增强(关联what) -->
    <bean id="transactionManager" class="com.shan.tx.TransactionManager"/>
    
    <aop:config proxy-target-class="false"> <!-- 属性proxy-target-class配置是否使用真实对象  -->
        <!-- 配置AOP切面 -->  
        <aop:aspect ref="transactionManager"> <!-- 关联what -->
            <!-- 2、where【where+what(地点+人物)】:在哪些包中的哪些类中的哪些方法上做增强 -->
            <aop:pointcut id="txPoint" expression="execution(* com.shan.service..*Service*.*(..))"/>
            
            <!-- 3、when【when+where+what(时间+地点+人物)】:在方法执行的什么时机(在哪里where-关联pointcut)做增强 -->
            <aop:before method="open" pointcut-ref="txPoint"/>
            <aop:after-returning method="commit" pointcut-ref="txPoint"/>
            <aop:after-throwing method="rollback" pointcut-ref="txPoint"/>
            <aop:after method="close" pointcut-ref="txPoint"/>
            <aop:around method="aroundMethod" pointcut-ref="txPoint"/>  
        </aop:aspect>
    </aop:config>




三、AOP 各种增强

1、增强的分类:

■ 根据被增强的方法的执行时机分为:前置增强、后置增强、异常增强、最终增强、环绕增强

  • 前置增强:权限控制、日志记录等 [被增强的方法执行之前]
  • 后置增强:提交事务、统计分析数据结果等 [被增强的方法正常执行之后(中途没有异常)]
  • 最终增强:回滚事务、记录日志异常信息等 [被增强的方法出现异常]
  • 最终增强:释放资源等 [finally最后操作]
  • 环绕增强:缓存、性能日志、权限、事务管理等 [可以自定义在被增强方法的什么时机执行(返回一个Object,参数processdingJoinpoint)]
图片.png



2、增强细节:

(1)获取异常的信息:

图片.png
public void rollback(Throwable ex) {
    System.out.println("回滚事务~,异常信息:" +ex.getMessage());
}


(2)获取被增强方法的信息【获取被增强方法的信息,并且可以传递给增强方法】:

  • Spring AOP:Joinpoint类 连接点,访问被增强方法的真实对象,代理对象,方法参数等
  • 可以作为前置、后置、异常、最终增强方法的参数,第一个参数
//可以作为前置、后置、异常、最终增强方法的参数,**`第一个参数`**    
public void open(JoinPoint jp) {
    System.out.println("开启事务~");
    System.out.println("代理对象:" +jp.getThis().getClass());
    System.out.println("目标对象:" +jp.getTarget().getClass());
    System.out.println("被增强方法的参数:" +Arrays.toString(jp.getArgs()));
    System.out.println("连接点方法的签名:" +jp.getSignature());
    System.out.println("当前连接点的类型:" +jp.getKind());
}


(3) 环绕增强方法调用真实对象的方法【参数processdingJoinpoint】:

  • 参数processdingJoinpoint:是JointPoin 的子类,只能用于环绕增强,作为第一个参数

    还可以调用真实对象中被增强的方法。

//调用真实对象的方法 ret = pjp.proceed();
public Object aroundMethod(ProceedingJoinPoint pjp) {
        Object ret = null;
        System.out.println("开启事务~");
        try {
            ret = pjp.proceed();//调用真实对象的方法
            System.out.println("调用真实对象的方法...~");
            System.out.println("提交事务~");
        } catch (Throwable e) {
            System.out.println("回滚事务~,错误信息:" + e.getMessage());
        }finally {
            System.out.println("关闭资源~");
        }
        return ret;
    }




四、使用注解配置AOP

AOP 注解:

(1)在配置文件中添加注解的解析器的配置【第三方程序(赋予注解的特殊功能)】:

  • 使用cglib注解:配置属性proxy-target-class="true"
   <!-- AOP注解的解析器 -->
   <aop:aspectj-autoproxy/>


(2)使用注解@Aspect配置一个AOP切面

  • @Pointcut (配置where)
  • @Before、@AfterReturning、@AfterThrowing、@After、@Around(配置when
@Component@Aspect //配置一个AOP切面
public class TransactionManager {
    
    //where
    //xml:<aop:pointcut id="txPoint" expression="execution(* com.shan.service..*Service*.*(..))"/>
    @Pointcut("execution(* com.shan.service..*Service*.*(..))")
    public void txPoint() {
        
    }
    
    //@Before("txPoint()")
    public void open(JoinPoint jp) {
        System.out.println("开启事务~");
    }

    //@AfterReturning("txPoint()")
    public void commit() {
        System.out.println("提交事务~");
    }
    //@AfterThrowing(value="txPoint()", throwing="ex")
    public void rollback(Throwable ex) {
        System.out.println("回滚事务~,异常信息:" +ex.getMessage());
    }
    //@After("txPoint()")
    public void close() {
        System.out.println("关闭资源~");
    }
    
    @Around("txPoint()")
    public Object aroundMethod(ProceedingJoinPoint pjp) {
        Object ret = null;
        System.out.println("开启事务~");
        try {
            ret = pjp.proceed();//调用真实对象的方法
            System.out.println("调用真实对象的方法...~");
            System.out.println("提交事务~");
        } catch (Throwable e) {
            System.out.println("回滚事务~,错误信息:" + e.getMessage());
        }finally {
            System.out.println("关闭资源~");
        }
        return ret;
    }
}



写在后面的话

       如果你觉得一乐的文章给您带来了一些收获,可以给个三连❤️ ,一乐会一如既往地更新有价值的博客。如果文章存在错误,也欢迎大家指出。还有,如果大家有什么好的学习技巧、学习感悟,也非常欢迎大家在评论区一起交流~

最后感谢大家的支持,谢谢~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352

推荐阅读更多精彩内容