【Spring学习】Spring的AOP模块应用详解
面向切面编程(AOP)的思想就是在执行某些代码前执行另外的代码,使程序更灵活、扩展性更好,可以随便地添加删除某些功能。
javaweb机制中的filter就是面向切面编程的例子。Tomcat会在程序运行的某个时机(即servlet执行前后),执行与servlet、JSP等毫无关系的filter代码。
AOP把一个业务流程分成几个部分,例如权限检查,业务处理,日志记录,每个部分单独处理,然后把它们组装成完整的业务流程。每个部分被称为切面(Aspect)或者关注点。Spring提供的AOP机制异常灵活,能够在任何类、任何方法的执行前、后添加拦截器。Spring推荐使用接口编程,Spring提供三种拦截器:方法前拦截器、返回后拦截器、异常抛出拦截器。
下面我们从一个简单的例子开始学习spring aop:
//Service接口
public interface IAopService{ public void withAop() throws Exception; //将会被拦截 public void withoutAop() throws Exception; //不会被拦截
} //Service接口 实现类
public class AopServiceImpl implements IAopService{ private String name; public void withAop() throws Exception{ System.out.println("有AOP的函数运行。name:"+name); if(name.trim().length() == 0){ throw new AccountException("name属性不能为空"); } } public void withoutAop() throws Exception{ System.out.println("没有AOP的函数运行。"); } public void setName(String name){ this.name = name; } public String getName(){ return this.name; }
}
方法前拦截器,检查name是否为空:
import org.springframework.aop.MethodBeforeAdvice;
public class MethodBeforeInterceptor implements MethodBeforeAdvice{ //调用对象的方法前执行该方法 //参数分别为被调用的方法、被调用方法的参数、对象 public void before(Method method,Object [] args,Object instance) throws Throwable{ System.out.println("即将执行方法:"+method.getName()); // if(instance instanceof AopServiceImpl){ String name = ((AopServiceImpl)instance).getName(); if(name == null){ throw new NullPointerException("name不能为空"); } } } }
返回后拦截器:
import org.springframework.aop.AfterReturningAdvice;
public class MethodAfterInteceptor implements AfterReturningAdvice{ //参数分别为方法返回值、被调用方法、方法参数、被拦截的对象 public void afterReturning(Object value,Method method,Object [] args,Object instance) throws Throwable{ System.out.println("方法:"+method.getName()+"执行完毕,返回值为:"+value); }
}
异常拦截器捕获异常 :
import org.springframework.aop.ThrowAdvice;
public class ThrowsInterceptor implements ThrowAdvice{ //参数分别为被调用的方法、方法参数、对象实例、抛出的异常 //前三个参数可以省略,第四个参数是必须的,这样设计是为了使开发者灵活地定义多个方法捕获各种不同的异常 public void afterThrowing(Method method,Object [] args,Object instance,AccountException ex) throws Throwable { System.out.println("方法:"+method.getName()+"抛出了异常:"+ex); } public void afterThrowing(NullPointerException ex) throws Throwable { System.out.println("抛出了异常:"+ex); } }
拦截器配置:
Spring无法将Service的实现类与拦截器直接组装,因为没有对应的setter、getter方法。安装时借助的是Spring的代理类,把拦截器安装到NameMatchMethodPointcutAdvisor中,把自动以的Service安装到ProxyFactoryBean中,然后组装到一块。
<!-- 方法前拦截器MethodBeforeInterceptor安装到NameMatchMethodPointcutAdvisor中 -->
<bean id="aopMethodBeforeInterceptor" class="org.springframework.aop.support. NameMatchMethodPointcutAdvisor"> <!-- 拦截器的实现类--> <property name="advice"> <bean class="com.lmb.spring. MethodBeforeInterceptor"> </property> <!-- 欲拦截的方法名--> <property name="mappedName" value="withAop"> </property>
</bean> <!-- 类似的方式配置返回后前拦截器MethodAfterInteceptor -->
<bean id="aopMethodAfterInterceptor" class="org.springframework.aop.support. NameMatchMethodPointcutAdvisor"> <property name="advice"> <bean class="com.lmb.spring. MethodAfterInteceptor"> </property> <property name="mappedName" value="withAop"> </property>
</bean> <!-- 类似的方式配置异常前拦截器MethodAfterInteceptor -->
<bean id="aopThrowsInterceptor" class="org.springframework.aop.support. NameMatchMethodPointcutAdvisor"> <property name="advice"> <bean class="com.lmb.spring.ThrowsInterceptor"> </property> <property name="mappedName" value="withoutAop"> </property>
</bean> <!-- Service实现类,安装到ProxyFactoryBean -->
<bean id="aopService" class="org.springframework.aop.ProxyFactoryBean"> <!-- 安装拦截器--> <property name="interceptorNames"> <list> <value>aopMethodBeforeInterceptor</value> <value>aopMethodAfterInterceptor</value> <value>aopThrowsInterceptor</value> </list> </property> <!-- 被拦截的对象--> <property name="target"> <bean class="com.lmb.spring.AopServiceImpl"> <property name="name" value="HelloSpring"></property> </bean> </property>
</bean>
切面Aspect:在本例中,方法withAop()、withoutAop()中都有一些代码,这些代码可以看做是AOP中的切面,可以将切面理解为模块;
通知Advisor:本例的三个拦截器都是实现自某个接口,从类名上看就知道三个拦截器都是AOP中的通知。一旦Spring符合条件,就会派发出通知,即一些需要执行的代码,能实现某种功能;
切入点Pointcut:在配置拦截器时,XML中只配置了withAop()方法使用拦截器,而withoutAop()方法没有配置拦截器,这种配置是借助于org.springframework.aop.support. NameMatchMethodPointcutAdvisor完成的。这就是一个切入点,配置时可以使用通配符。该类说明上也带有Advisor是因为它也是用通知实现的;
AOP的相关概念总结:
方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用spring的 Advisor或拦截器实现。
连接点(Joinpoint): 程序执行过程中明确的点,如方法的调用或特定的异常被抛出。
通知(Advice): 在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice。
切入点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上。
引入(Introduction): 添加方法或字段到被通知的类。 Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来配置Advice和代理类要实现的接口。
目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。
AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。
织入(Weaving): 组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。
【Spring学习】Spring的AOP模块应用详解相关推荐
- Spring学习(七)bean装配详解之 【通过注解装配 Bean】【自动装配的歧义解决】...
本文借鉴:Spring学习,@Bean 的用法(特此感谢!) 自动装配 1.歧义性 我们知道用@Autowired可以对bean进行注入(按照type注入),但如果有两个相同类型的bean在IOC容器 ...
- Spring学习(六)bean装配详解之 【通过注解装配 Bean】【基础配置方式】
本文借鉴:Spring学习(特此感谢!) 通过注解装配 Bean 1.前言 优势 1.可以减少 XML 的配置,当配置项多的时候,XML配置过多会导致项目臃肿难以维护 2.功能更加强大,既能实现 XM ...
- Spring学习(五)bean装配详解之 【XML方式配置】
本文借鉴:Spring学习(特此感谢!) 一.配置Bean的方式及选择 配置方式 在 XML 文件中显式配置 在 Java 的接口和类中实现配置 隐式 Bean 的发现机制和自动装配原则 方式选择的原 ...
- spring学习(8):log4j.properties 详解与配置步骤
一.入门实例 1.新建一个JAva工程,导入包log4j-1.2.17.jar,整个工程最终目录如下 2.src同级创建并设置log4j.properties ### 设置### log4j.root ...
- Spring Boot的每个模块包详解
Spring Boot的每个模块包详解,具体如下: 1.spring-boot-starter 这是Spring Boot的核心启动器,包含了自动配置.日志和YAML. 2.spring-boot-s ...
- 跟着小马哥学系列之 Spring AOP(Advisor 详解)
学好路更宽,钱多少加班. --小马哥 简介 大家好,我是小马哥成千上万粉丝中的一员!2019年8月有幸在叩丁狼教育举办的猿圈活动中知道有这么一位大咖,从此结下了不解之缘!此系列在多次学习极客时间< ...
- Spring基于注解TestContext 测试框架使用详解
原创整理不易,转载请注明出处:Spring基于注解TestContext 测试框架使用详解 代码下载地址:http://www.zuidaima.com/share/1775574182939648. ...
- Spring Boot 使用 HikariCP 连接池配置详解
Spring Boot 使用 HikariCP 连接池配置详解 HikariCP 是一个高性能的 JDBC 连接池组件. Spring Boot 2.x 将其作为默认的连接池组件,项目中添加 spri ...
- Spring三级缓存解决循环依赖问题详解
spring三级缓存解决循环依赖问题详解 前言 这段时间阅读了spring IOC部分的源码.在学习过程中,自己有遇到过很多很问题,在上网查阅资料的时候,发现很难找到一份比较全面的解答.现在自己刚学习 ...
最新文章
- 局域网与网络工程课堂笔记(1)(2)
- PHP性能调优,PHP慢日志---PHP脚本执行效率性能检测之WebGrind的使用
- 【错误记录】Mac 中 IntelliJ IDEA 运行 Python 程序报错 ( End of statement expected )
- LeetCode算法题5:双指针
- VTK:图片之ResizeImage
- Qt工作笔记-对QThread使用的进一步认识(exec及对象在哪个线程创建)
- (转) 淘淘商城系列——CMS内容管理系统工程搭建
- 剑桥女博士创立情绪识别 AI 公司,帮助自闭症患者理解他人表情
- 了解 PerformancePoint 仪表板设计器
- C编程语言中整型变量在内存中的存储形式介绍
- BZOJ_1029_[JSOI2007]_建筑抢修_(贪心+优先队列)
- 学习矩阵分析与应用过程中的点滴记录(一)
- catia设计树_在CATIA目录树上**零件号原来这么简单!
- 笔记本电脑切换Fn功能键
- 自上而下 or 自下而上?企业部署RPA的2种策略
- 阿里云账号注册实名认证详细教程(支付宝实名认证)
- 家用洗地机有什么优缺点?入门级家用洗地机
- 模块内高内聚?模块间低耦合?MVC+EF演示给你看!
- pg批量插入_postgresql大批量数据导入方法
- java程序设计 秒表计时器_【Java】Java计时器(秒表)