Spring的第三天AOP之xml版
Spring的第三天AOP之xml版
AOP介绍
AOP(Aspect Oriented Programming),面向切面编程。它出来的目的并不是去取代oop,而是对它的完善和补充。在oop中,人们的是去定义纵向的关系,但是会出现一个问题:在程序中,日志代码往往是横向的地散布在各种对象层次中,而在oop的模式设计中,导致了大量重复工作的代码。
可以这样说:oop是面向名词领域,AOP是面向动词领域。AOP适合通用的工作,不适合个性化的工作。
图来自网络,侵删

在AOP中,我们将那些与多个类相关的行为放在一起变成一个模块,命名为Aspect
【切面】。讲个故事:
村里来了一个
通告
,以前是到每家每户去通知,假如通告进行了改变,又要重新进行通知,然后村里面的人觉得太麻烦了,就做了一个声音传输管道,每当有通告来的时候,村长
就选择要通知的人
,告诉他们某个时间
去做通告里面的东西,然后打开管道进行通知。
通告:通知(Advice)
就是你想要的东西,比如说日志,事物。
人:PointCut【切入点】
切入点里面定义了Advice发生的地点,例如某个类或方法的名称,为被切的地方。
时间:Joinpoint【连接点】
连接点就是告诉程序什么时候去使用通知,例如当方法被调用时,或者是异常抛出时。
村长:Proxy【代理】
Proxy不能算是AOP的家庭成员,它是一个管理部门,管理AOP如何融入OOP,是AOP的实践者。同时AOP的代理离不开spring的IOC容器。在Spring Framework中,AOP代理是JDK动态代理或CGLIB代理。
那么什么是切面呢?
切面其实就是Advice+PointCut,代表了切面的所有元素,而将切面织入代码中就是依靠Proxy
maven依赖
导入Spring依赖和aop依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.8.RELEASE</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.11</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
头部文件xmlns文件配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
类的java代码
package com.weno.pojo;
public class User {
public void print(){
System.out.println("我这是在执行一个方法");
throw new RuntimeException("我故意的报错");
}
public String msg(){
return "竟然有返回值";
}
}
建议类:
package com.weno.aop;
public void beforeMethod(){
System.out.println("一千年以前");
}
public void afterMethod(){
System.out.println("一千年以后");
}
public void returnMethod(Object rvt){
System.out.println("返回值>>>>>>"+rvt);
System.out.println("方法返回");
}
public void errorMethod(){
System.out.println("程序竟然报错了");
}
}
xml版本的使用
首先先说一下切入点,切入点分为:
前置通知:在连接点之前运行但无法阻止执行流程进入连接点的建议(除非它引发异常,该异常将中断当前方法链的执行而返回)。
后置通知:在连接点
正常
完成后运行的建议(例如,如果方法返回而不抛出异常)。异常通知:如果方法通过抛出异常退出,则执行建议。
后置最终通知:无论连接点退出的方式(正常或异常返回),都要执行建议。
环绕通知:环绕在连接点处的方法所执行的通知,环绕通知可以在方法调用之前和之后自定义任何行为,并且可以决定是否执行连接点处的方法、替换返回值、抛出异常等等。环绕通知还需要负责决定是继续处理join point(调用ProceedingJoinPoint的proceed方法)还是中断执行。
前置通知,后置通知,异常通知,返回通知
<bean class="com.weno.pojo.User" id="user"/>
<bean class="com.weno.aop.Method" id="method"/>
<aop:config>
<!--定义一个切面-->
<aop:aspect ref="method">
<!--切点,定义切点的id exexution后面写要切入的地点:在print这个方法进行切-->
<aop:pointcut id="positon" expression="execution(* com.weno.pojo.User.print())"/>
<!-- 切的时间 method表示切的方法 -->
<!-- beforeMethod 在执行方法之前切入 -->
<aop:before method="beforeMethod" pointcut-ref="positon"/>
<!-- 在执行方法之后切入 -->
<aop:after method="afterMethod" pointcut-ref="positon"/>
<!-- 在方法报错的时候切入 -->
<aop:after-throwing method="errorMethod" pointcut-ref="positon"/>
<!-- 在方法有返回值的时候切
同时可以加上returning,将值传给returnMethod()方法
-->
<aop:after-returning method="returnMethod" returning="rvt" pointcut="execution(* com.weno.pojo.User.msg())"/>
</aop:aspect>
</aop:config>
测试代码一:
@Test
public void m01(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/spring-test1.xml");
// 在这里,如果直接通过new实例化User,那么aop功能将失效,因为AOP是要在spring IOC容器里面实现的
User user = ctx.getBean("user",User.class);
user.print();
}
输出结果
一千年以前
我这是在执行一个方法
一千年以后
程序竟然报错了
测试代码二:
@Test
public void m03(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/spring-test1.xml");
User user = ctx.getBean("user",User.class);
user.msg();
}
结果:
返回值>>>>>>竟然有返回值
方法返回
环绕通知
环绕通知是所有通知类型中功能中最为强大的,能够全面地控制连接点,甚至能够控制方法是否执行,同时,他还可以实现before和after的功能。
切面程序的代码
public void aroundMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//允许程序进行执行
proceedingJoinPoint.proceed();
}
public void aroundMethod2(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//允许程序进行执行,并将其参数进行改变。
proceedingJoinPoint.proceed(new String[]{"你最帅"});
}
被切的程序
public void msg1(){
System.out.println("这是米有参数的msg");
}
public void msg2(String msg){
System.out.println("进行执行方法输出"+msg);
}
xml文件配置
<aop:around method="aroundMethod" pointcut="execution(* com.weno.pojo.User.msg1())"/>
<aop:around method="aroundMethod2" pointcut="execution(* com.weno.pojo.User.msg2(..))"/>
测试文件
@Test
public void m04() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/spring-test1.xml");
User user = ctx.getBean("user", User.class);
user.msg1();
user.msg2("我好帅");
}
结果
这是米有参数的msg
//在这里面,参数进行了改变,由我好帅变成了你最帅
进行执行方法输出你最帅
JoinPoint的神奇之处
这个是官方文档截取过来的
使用上面的那个例子来获得参数:
public void aroundMethod2(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object[] args = proceedingJoinPoint.getArgs();
System.out.println(Arrays.toString(args));
//允许程序进行执行,并将其参数进行改变。
proceedingJoinPoint.proceed(new String[]{"你最帅"});
}
输出结果当然是:
这是米有参数的msg
[我好帅]
进行执行方法输出你最帅
当然,如果你将Object[] args = proceedingJoinPoint.getArgs(); System.out.println(Arrays.toString(args));
放在后面,那输出参数当然就变成了[你最帅]。
基本数据类型和包装类对于execution严格区分
首先先简单的介绍一下execution,先定义一个表达式:
execution(* com.weno...(..))
在这里面
标识符 | 含义 |
---|---|
execution | 表达式的主体 |
第一‘*’号 | 表示返回值的类型,*号代表任意类型 |
com.weno | 代表包,被切的地方 |
包后面的‘..’ | 代表当前包及其子包 |
第二个‘*’号 | 代表类,*号代表所有类 |
第三个‘*’号 | 代表方法,‘*’代表任意方法 |
(..) | 括号里面表示参数,两个点表示任意参数,也可以不加 |
在execution表达式中,参数严格区分基本数据类型和包装类。例如:
在com.weno.pojo.User.hasAge()中
public void hasAge(Integer age){
}
<!-- 这样是可以切到的 -->
<aop:before method="beforeAge" pointcut="execution(* com.weno.pojo.User.hasAge(Integer))"/>
<!-- 加入将Integer换成int,那么,无法执行切面 -->
<aop:before method="beforeAge" pointcut="execution(* com.weno.pojo.User.hasAge(int))"/>
好了,Spring的第三天就到这里了。明天就星期六了,IG加油(ง •_•)ง

在下一篇博客中,我将介绍一下aop注解版的使用

Spring的第三天AOP之xml版的更多相关文章
- Spring的第四天AOP之注解版
Spring的第四天AOP之注解版 ssm框架 spring 在上一篇博客中,介绍了Spring的AOP的xml版本的使用,在这篇博客中,我将介绍一下,注解版的使用. 常用注解 注解 通知 @Aft ...
- 深入学习Spring框架(三)- AOP面向切面
1.什么是AOP? AOP为 Aspect Oriented Programming 的缩写,即面向切面编程, 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术..AOP是OOP的延续, ...
- Spring入门(三)— AOP注解、jdbc模板、事务
一.AOP注解开发 导入jar包 aop联盟包. aspectJ实现包 . spring-aop-xxx.jar . spring-aspect-xxx.jar 导入约束 aop约束 托管扩展类和被扩 ...
- Spring 学习(三)AOP
(1)AOP概述 - AOP:面向切面编程,扩展功能不修改源代码实现 - AOP采取横向抽取机制,取代了传统的纵向继承体系重复性代码 (2)AOP底层原理 原始方法------->纵向继承体系 ...
- spring源码 — 三、AOP代理生成
AOP代理生成 AOP就是面向切面编程,主要作用就是抽取公共代码,无侵入的增强现有类的功能.从一个简单的spring AOP配置开始: <?xml version="1.0" ...
- Spring框架第三篇之基于XML的DI注入
一.注入分类 Bean实例在调用无参构造器创建空值对象后,就要对Bean对象的属性进行初始化.初始化是由容器自动完成的,称为注入.根据注入方式的不同,常用的有两类:设值注入.构造注入.实现特定接口注入 ...
- Spring入门(三)——AOP
1. AOP aspect object programming ,简单来说就是把重复的代码抽取出来,然后再需要用到的地方进行切入,这里讲解基于接口的注解实现 2. 了解 关注点:即重复的代码 切面: ...
- Spring Boot2 系列教程 (十三) | 整合 MyBatis (XML 版)
前言 如题,今天介绍 SpringBoot 与 Mybatis 的整合以及 Mybatis 的使用,之前介绍过了 SpringBoot 整合MyBatis 注解版的使用,上一篇介绍过 MyBatis ...
- Spring (五):AOP
本文是按照狂神说的教学视频学习的笔记,强力推荐,教学深入浅出一遍就懂!b站搜索狂神说或点击下面链接 https://space.bilibili.com/95256449?spm_id_from=33 ...
随机推荐
- Python基础(六)
- 2019.02.17 spoj Query on a tree VII(链分治)
传送门 跟QTREE6QTREE6QTREE6神似,改成了求连通块里的最大值. 于是我们对每条链开一个heapheapheap维护一下即可. MDMDMD终于1A1A1A链分治了. 代码: #incl ...
- java框架学习_mybaties
Mybatis第一天 框架课程 1. 课程计划 第一天: 1.Mybatis的介绍 2.Mybatis的入门 a) 使用jdbc操作数据库存在的问题 b) Mybatis的架构 c) Mybati ...
- 提取日志中出现的userId或其他信息
项目上线后经常出现需要统计用户数据.接口请求等.完美的情况下,在项目开始前就设计好哪些request.中间过程需要落地到db.或以一定格式存入专门的log中,但也常需要同学们临时去业务日志中grep ...
- uva1673(后缀自动机)
后缀自动机还是只会打板子,已经知道它是个什么东西了,但还是和它的构造联系不起来..先背板子吧. 后缀自动机有一个很好的特性就是可以涵盖所有不重复的子串,我们利用这一点在它上面dp就行了: 代码参考:h ...
- HDU 2639 01背包(分解)
http://acm.hdu.edu.cn/showproblem.php?pid=2639 01背包第k优解,把每次的max分步列出来即可 #include<stdio.h> #incl ...
- salt 配置管理
索引 saltstack入门 salt state sls 描述文件 saltstack配置管理高级功能 saltstack入门 192.168.86.3 salt 修改 [root@Zabbix-s ...
- iOS调用QQ发起临时会话
iOS调用QQ发起临时会话 iOS调用qq前先判断是否安装qq, 之后通过OpenURL打开对用的qq NSURL *url = [NSURL URLWithString:@"mqq://& ...
- 收藏的blog
https://www.cnblogs.com/xifengxiaoma/tag/vue/ https://www.cnblogs.com/xifengxiaoma/p/9400200.html
- AndroidStudio制作登录和注册功能的实现,界面的布局介绍
前言 大家好,给大家带来AndroidStudio制作登录和注册功能的实现,界面的布局介绍的概述,希望你们喜欢 每日一句: Success is connecting with the world a ...