4、spring核心AOP
Spring AOP
1. Spring AOP 概述 1-1
1.1. 何为AOP? 1-1
1.2. AOP要解决什么问题? 1-1
1.3. AOP实际项目应用场景? 1-2
1.4. AOP底层原理实现分析? 1-2
2. Spring AOP 编程实现 2-2
2.1. AOP 基本步骤 2-2
2.2. AOP 基于xml实现 2-2
2.2.1. 创建项目添加依赖 2-3
2.2.2. 添加spring配置文件 2-3
2.2.3. 创建核心业务类 2-4
2.2.4. 创建日志处理类 2-4
2.2.5. 配置bean对象 2-5
2.2.6. 编写测试类 2-6
3. 总结 3-7
3.1. 重点和难点分析 3-7
3.2. 常见FAQ 3-7
1. Spring AOP 概述
1.1. 何为AOP?
AOP 是软件设计领域中的面向切面编程,它是面向对象编程的一种补充和完善实际项目中我们通常将面向对象理解为一个静态过程(例如一个系统有多少模块,一个模块有哪些对象,对象有哪些属性),面向切面理解为一个动态过程(在对象运行时动态织入一些功能。)
1.2. AOP要解决什么问题?
实际项目中通常会将系统两大部分:核心关注点和非核心关注点
思考?
编程过程中首先要完成的是什么?核心关注点(核心业务)
非核心关注点如何切入到系统中?硬编码(违背OCP),AOP(推荐)
AOP就是要在基于OCP在不改变原有系统核心业务代码的基础上动态添加一些扩展功能。
1.3. AOP实际项目应用场景?
AOP 通常应用于日志的处理,事务处理,权限处理,缓存处理等等。
1.4. AOP底层原理实现分析?
AOP底层基于代理机制实现功能扩展:(了解)
1) 假如目标对象(被代理对象)实现接口,则底层默认采用JDK动态代理机制为目标对象创建代理对象(目标类和代理类会实现共同接口)
2) 假如目标对象(被代理对象)没有实现接口,则底层默认采用CGLIB代理机制为目标对象创建代理对象(默认创建的代理类会继承目标对象类型)。
2. Spring AOP 编程实现
2.1. AOP 基本步骤
step1:创建maven java 项目
step2:添加aop依赖
step3:配置aop 核心(基于xml,基于注解)
step4:定义核心业务(核心关注点):推荐先写接口再写实现类
step5:定义扩展业务(非核心关注点)
step6:基于配置实现非核心业务的切入
step7:编写测试类进行单元测试
2.2. AOP 基于xml实现
通过AOP为核心业务类添加日志处理
2.2.1. 创建项目添加依赖
创建maven java 项目然后添加依赖
2.2.2. 添加spring配置文件
2.2.3. 创建核心业务类
创建接口
public interface HelloService {void sayHello(String msg); }
创建接口实现类
public class HelloServiceImpl implements HelloService {public void sayHello(String msg) {//假设这条语句是我们系统中的核心业务 System.out.println(msg);} }
2.2.4. 创建日志处理类
public class LoggingAspect {public void beforeMethod(){System.out.println("method start");}public void afterMethod(){System.out.println("method end");} }
2.2.5. 配置bean对象
<?xml version="1.0" encoding="UTF-8"?> <beans default-lazy-init="true"xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:util="http://www.springframework.org/schema/util"xmlns:jpa="http://www.springframework.org/schema/data/jpa"xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsdhttp://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd"> <!-- 核心业务对象 --><bean id="helloService"class="spring.beans.HelloServiceImpl"/><!-- 配置非核心业务对象(日志处理对象):切面 --><bean id="log" class="spring.aop.LoggingAspect"/><!-- AOP配置(切入点,切面) --> <aop:config><!-- 配置切入点 --><aop:pointcut expression="within(spring.beans.HelloServiceImpl)" id="logPointCut"/><!-- 配置日志处理 --><aop:aspect ref="log" ><aop:before method="beforeMethod" pointcut-ref="logPointCut"/><aop:after method="afterMethod"pointcut-ref="logPointCut"/></aop:aspect></aop:config> </beans>
2.2.6. 编写测试类
//1.初始化spring容器ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");//2.获取Bean对象HelloService helloService=ctx.getBean("helloService",HelloService.class);//3.执行业务helloService.sayHello("CGB1710");//proxy的方法//4.释放资源ctx.close();
2.3. AOP 基于注解实现
先参考AOP参考文档进行整理,后续上传
1.1.1. 创建maven 项目添加依赖
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>4.3.9.RELEASE</version></dependency><!--Spring AOP的实现依托于Aspect框架所以要引用1.8.5有问题--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.8.9</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.9</version></dependency>
1.1.2. 创建核心业务类
定义一个订单接口,此接口中定义多个业务操作。
public interface OrderService {public void saveOrder();public void deleteOrder(); }
1.1.3. 创建时间处理类
将此时间处理类作为核心业务增强(一个横切面对象)类,用于输出业务开始执行时间,以及业务结束执行时间。
横切面对象主要由两部分构成:切入点(用于@Pointcut标识),以及功能增强(用通知@Before,@After等进行标识)
@Aspect @Service public class TimeAspect {@Pointcut("bean(orderService)")public void pointcut(){}/**增强功能:前置通知(业务方法执行之前执行)*/@Before("pointcut()")public void begin(){System.out.println("start:"+System.nanoTime());}/**增强功能:最终通知(业务方法执行最后执行,*无论业务方法是否执行成功,此功能都要执行)*/@After("pointcut()")public void end(){System.out.println("end:"+System.nanoTime());} }
其中:
@Aspect 注解用于标识此类为一个AOP横切面对象
@Pointcut 注解用于定义本类中的切入点,本案例中切入点表达式用的是bean表达式,这个表达式以bean开头,bean括号中的内容为一个spring管理的某个bean对象的id。
@Before 用于定义一个前置通知(满足切入点表达式的核心业务方法执行之前要执行的一个操作)
@After 用于定义一个后置通知(满足切入点表达式的核心业务方法执行之后要执行的一个操作)
术语增强:
切面:用于封装扩展业务的一个类的对象。
通知:切面扩展业务中的一个操作。
1.1.4. 配置AOP实现
对于基于注解方式的配置一般有两种方式,一种是直接在xml核心配置文件中进行配置,还有一种在类中基于注解进行配置。例如
基于xml方式配置对注解的应用
<?xml version="1.0" encoding="UTF-8"?> <beans default-lazy-init="true"xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:util="http://www.springframework.org/schema/util"xmlns:jpa="http://www.springframework.org/schema/data/jpa"xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsdhttp://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd"> <!-- 配置对类组件的扫描 --><context:component-scan base-package="com.spring"/><!-- 启用AOP注解(自动为目标对象创建代理对象) --><aop:aspectj-autoproxy/></beans>
在类中基于注解方式的配置
@ComponentScan("com.spring.beans") @EnableAspectJAutoProxy public class AppConfig {}
1.1.5. 编写测试类
public class TestAOP01 {public static void main(String[] args) {//1.初始化容器ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");//2.获取bean对象OrderService os=(OrderService)ctx.getBean("orderService", OrderService.class);//3.执行业务方法 os.saveOrder();os.deleteOrder();//4.释放资源 ctx.close();} }
基于类中注解方式配置的测试实现
public class TestAOP02 {public static void main(String[] args) {//1.初始化容器对象AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext(AppConfig.class);//2.获取Bean对象OrderService orderService=ctx.getBean("orderService", OrderService.class);//3.执行业务 orderService.saveOrder();//orderService.deleteOrder();//4.释放资源 ctx.close();} }
基于类的注解配置,初始化工厂时需要初始化
AnnotationConfigApplicationContext对象。
2. Spring AOP 编程增强
2.1. 切面表达式增强
Spring中通过切入点表达式定义具体切入点,其常用AOP切入点表达式定义及说明:
|
指示符 |
作用 |
bean |
用于匹配指定bean id的的方法执行 |
|
within |
用于匹配指定包名下类型内的方法执行 |
|
execution |
用于进行细粒度方法匹配执行具体业务 |
2.1.1. Bean表达式应用增强
bean应用于类级别,实现粗粒度的控制:
bean(UserServiceImpl)) |
指定一个类 |
bean(*Service) |
指定所有的后缀为service的类 |
2.1.2. Within表达式应用增强
within应用于类级别,实现粗粒度的控制:
within(aop.service.UserServiceImpl)) |
指定类,只能指定一个类 |
within(aop.service.*)) |
只包括当前目录下的类 |
within(aop.service..*)) |
指定当前目录包含所有子目录中的类 |
2.1.3. Execution表达式应用增强
execution方法级别,细粒度的控制:
语法:execution(返回值类型 包名.类名.方法名(参数列表))
execution(void aop.service.UserServiceImpl.addUser()) |
匹配方法 |
execution(void aop.service.PersonServiceImpl.addUser(String)) |
方法参数必须为字符串 |
execution(* aop.service..*.*(..)) |
万能配置 |
2.2. 切面通知增强
在AOP编程中有五种类型的通知:
1) 前置通知
2) 后置通知
3) 异常通知
4) 最终通知
5) 环绕通知
2.2.1. Xml方式通知配置增强
切入点及前置通知,后置通知,返回通知,异常通知,环绕通知的配置
<aop:config><aop:pointcut id="pc"expression="execution(* com.company.spring.service..*.*(..))" ><aop:aspect ref="loggingAspect"><aop:before method="beforeMethod" pointcut-ref="pc"/><aop:after method="afterMethod" pointcut-ref="pc"/><aop:after-returning method="returnMethod"pointcut-ref="pc"/><aop:after-throwing method="throwMethod" pointcut-ref="pc"/></aop:aspect></aop:config>
切入点及环绕通知的配置(了解)<aop:config><aop:pointcut id="pc"expression="execution(* com.company.spring.service..*.*(..))" ><aop:aspect ref="loggingAspect"><aop:around method="aroundMethod" pointcut-ref="pc"/></aop:aspect></aop:config>
2.2.2. 注解方式通知配置增强
切入点及前置通知,后置通知,返回通知,异常通知,环绕通知的配置
@Aspect @Service public class TxAspect {@Before("bean(orderService)")public void startTx(){System.out.println("开启事务");}@AfterReturning("bean(orderService)")public void commitTx(){System.out.println("提交事务");}@AfterThrowing("bean(orderService)")public void rollbackTx(){System.out.println("回滚事务");}@After("bean(orderService)")public void closeResource(){System.out.println("释放资源");} }
切入点及环绕通知的配置
@Component @Aspect public class TxManager {@Pointcut("execution(com.company.spring.service..*.*(..))")public void pointCut() {}@Around("pointCut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("事务开始");Object result = joinPoint.proceed();System.out.println("事务结束");return result;} }
2.3. 切面执行顺序配置增强
实际项目中可能会有多个切面,切面之间的执行可能需要一定的顺序
2.3.1. Xml方式配置执行顺序
<aop:config><aop:pointcut id="pc"expression="execution(* com.company.spring.service..*.*(..))"/><aop:aspect ref="loggingAspect" order="1"><aop:around method="aroundMethod" pointcut-ref="pc"/></aop:aspect><aop:aspect ref="txManager" order="2"><aop:around method="aroundMethod" pointcut-ref="pc"/></aop:aspect></aop:config>
2.3.2. 注解方式配置执行顺序
注解方式顺序配置需要借助@Order注解
@Order(1) @Aspect @Component public class TxManager {@Pointcut("execution(* com.company.spring.service..*.(..))")public void pointCut() {}@Around("pointCut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("事务开始");Object result = joinPoint.proceed();System.out.println("事务结束");return result;} }
注解方式顺序配置
@Order(2) @Aspect @Component public class LoggingAspect {@Pointcut("execution(* com.company.spring.service..*.(..))")public void pointCut() {}@Before("pointCut()")public void beforeMethod() {System.out.println("beforeMethod");}@Before("pointCut()")public void afterMethod() {System.out.println("afterMethod");} }
3. 总结
3.1. 重点和难点分析
|
3.2. 常见FAQ
- 什么是OCP原则(开闭原则)
- 什么是单一职责原则(一个类或接口的职责不要太多)
- spring中AOP的有哪些配置方式(xml和注解)
- Spring 中AOP 的通知有哪些基本类型
- Spring 中AOP是如何为Bean对象创建代理对象的
3.3. 作业
|
转载于:https://www.cnblogs.com/xiangyuqi/p/8655444.html
4、spring核心AOP相关推荐
- Spring核心AOP(面向切面编程)总结
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/75208354冷血之心的博客) 目录 1.AOP概念: 2.AOP特 ...
- Spring核心AOP(面向切面编程)
AOP(面向切面编程) 原理 相关术语 系统日志增强 异常抛出增强 最终增强 环绕增强 使用注解实现AOP AspectJ 转载于:https://www.cnblogs.com/xhddbky/p/ ...
- spring框架 AOP核心详解
AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...
- Spring核心机制IoC与AoP梳理
Spring核心机制IoC与AoP梳理 文章目录 Spring核心机制IoC与AoP梳理 IoC介绍 IoC案例介绍 pom文件中IoC环境引入 自己new对象方法举例(正转) IoC创建对象 基于X ...
- [Spring 深度解析]第4章 Spring之AOP
第4章 ◄Spring之AOP► 在上一章节中,我们大致了解了Spring核心容器,了解了IOC思想在Spring中的具体应用Bean容器以及Bean的配置与使用,这一章我们将开始学习AOP在Spri ...
- Spring对AOP的支持
Spring对AOP的支持<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" ...
- Spring 容器AOP的实现原理——动态代理
本文来自极客学院 Spring 容器AOP的实现原理--动态代理 之前写了一篇关于IOC的博客--<Spring容器IOC解析及简单实现>,今天再来聊聊AOP.大家都知道Spring的两大 ...
- Spring的AOP思想和实现AOP思想的框架AspectJ
章节目标:详细解释什么是Spring AOP思想和对于该思想实现的AspectJ框架的实现用法. 一.AOP面向切面编程 1.AOP概述 AOP(Aspect Orient Programming)面 ...
- Spring核心——IOC处理器扩展
为什么80%的码农都做不了架构师?>>> 非侵入式框架 Spring一直标注自己是一个非侵入式框架.非侵入式设计的概念并不新鲜,目标就是降低使用者和框架代码的耦合,毕竟框架的开 ...
最新文章
- CTFshow 反序列化 web264
- Python(1) 整型与浮动型
- EMR Spark Runtime Filter性能优化
- [BUAA软工]团队贡献分博客
- 剑指offer——面试题5:从尾到头打印链表
- DWR整合Spring
- CSS文件在jsp 文件中应该放的位置
- 五大列级庄_酒庄拉菲古堡Chateau Lafite Rothschild, 波尔多五大一级庄之首
- 无法保存此文档。它可能是只读的,或者正在被其他应用程序使用
- EDEM基础操作步骤
- Java实现PDF文件生成并且打印pdf文件(附demo)
- 人工智能AI系列 - 元宇宙 - 2D虚拟人
- ACM/ICPC 2018亚洲区预选赛北京赛站网络赛-B:Tomb Raider(二进制枚举)
- word文档分栏怎么设置
- 【工具】pip安装不在当前虚拟环境中
- PowerDesigner 16逆向工程,MySQL数据库的生成PDM物理数据模型文件
- Linux比较常用的终端快捷键使用
- 英国化学实验室的管理模式
- 你真的需要Apple TV吗?不如自制一个Android TV!
- Mini Story 总结
热门文章
- Creating a Java VM from Android Native Code
- Android插件化原理解析——Hook机制之Binder Hook
- Android应用安全之Content Provider安全
- Android自定义View实现滴滴验证码输入框效果
- 南核目录2020pdf_北核+南核|《消费经济》2020年重点选题
- mybatis批量夺标添加_MyBatis+MySQL同时执行多条SQL,实现多表插入数据
- debian linux 内核 3.14-1 显示器 很暗,Ubuntu 与 Linux Mint 用户安装 Kernel 3.14.1 内核
- python操作mongodb语法_python 操作MongoDB
- mqtt调试助手_物联网入门,如何使用MQTT协议,连接Tlink物联网平台
- 三相逆变器双pi控制器参数如何调节_Boost 变换器 PI参数设计举例