Spring AOP

面向切面(儿)编程(横切编程)

  1. Spring 核心功能之一

    • Spring 利用AspectJ 实现.
  2. 底层是利用 反射的动态代理机制实现的
  3. 其好处: 在不改变原有功能情况下, 为软件扩展(织入)横切功能

生活中的横切功能事例:

软件中的横切编程需求:

AOP其原理如下:

切面组件

是封装横切功能的Bean组件, 用于封装扩展功能方法.

AOP配置步骤

  1. 引入aspectj包

    <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.5.4</version>
    </dependency>
    
  2. 创建切面组件对象:

    @Component //将当前类纳入容器管理
    @Aspect //Aspect 切面(儿), 声明当前的bean是
    // 一个切面(儿)组件!
    public class DemoAspect implements Serializable{//@Before 在方法执行之前执行//userService 的所有方法@Before("bean(userService)")public void test(){System.out.println("Hello World!");}}
    
  3. 配置AOP功能 resource/conf/spring-aop.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc"  xmlns:jee="http://www.springframework.org/schema/jee" 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-3.2.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsdhttp://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsdhttp://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsdhttp://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd"><!-- 开启组件扫描 --><context:component-scan base-package="cn.tedu.cloudnote.aop"/><!-- 开启aop, 底层使用aspectj --><aop:aspectj-autoproxy/>    </beans>
    
  4. 测试: 在登录功能执行期间, 登录功能被扩展了 Hello World!

注意: spring-aop.xml 的文件名必须符合 spring-*.xml 否则无法被加载 注意: Spring AOP 是利用 Aspectj AOP实现的, 在使用Spring AOP时候必须引入 Aspectj 的jar包.

如上代码的工作原理:

通知

是指: 切面方法的执行时机, 用于声明切面方法在被拦截方法之前或者之后执行

常用的有5个:

  1. @Before

    • 在被拦截方法之前执行
  2. @AfterReturning
    • 在方法正常执行以后执行
  3. @AfterThrowing
    • 在方法出现异常以后执行
  4. @After
    • 无论方法是否有异常都会执行
  5. @Around
    • 环绕方法执行

注意: 通知只表示执行时机, 不保证执行次序, @After经常在@AfterThrowing 之前出现.

通知原理:

案例:

@Component
@Aspect
public class TestAspect implements Serializable{@Before("bean(userService)")public void before() {System.out.println("before()");}@AfterReturning("bean(userService)")public void afterReturning(){System.out.println("afterReturning");}@AfterThrowing("bean(userService)")public void afterThrowing(){System.out.println("afterThrowing");}@After("bean(userService)")public void after(){System.out.println("after");}}

@Around 是环绕通知, 是万能的通知

Around 工作原理类似于 Servlet Filter 工作过程

原理:

案例:

@Component
@Aspect
public class AroundAspect implements Serializable{//环绕通知, test 方法将代理业务方法//Object 返回代表业务方法的返回值//Throwable 是业务方法执行期间的异常@Around("bean(userService)")public Object test(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("执行业务之前!");//调用业务方法try{//@BeforeObject obj=joinPoint.proceed();System.out.println("抓到:"+obj);//@ArterReturningreturn obj;}catch(Throwable e){//@AfterThrowingthrow e;}finally{System.out.println("执行业务之后!");//@Arfter}}
}

测试...

审计业务层方法的性能案例:

//性能审计 AOP
@Component
@Aspect
public class ProcAspect implements Serializable{@Around("execution(* cn.tedu.cloudnote.service.*Service.*(..))")public Object test(ProceedingJoinPoint joinPoint)throws Throwable{long t1 = System.nanoTime();//调用业务方法Object obj=joinPoint.proceed();Signature s=joinPoint.getSignature();//Signature 签名: 这里是方法签名(方法名+参数类型列表)long t2 = System.nanoTime();System.out.println(s+"执行时间:"+(t2-t1)); return obj;}
}

Signature 签名: 这里是方法签名(方法名+参数类型列表)

切入点

是指 切面组件的切入位置: 哪个类, 哪个对象, 哪个方法

  1. Bean组件切入点

    • 语法: bean(bean组件ID)
    • bean(userService)
    • bean(userService) || bean(bookService)
    • bean(*Service)
  2. within 类切入点:
    • 语法: within(类的全名)
    • within(cn.tedu.cloudnote.service.*Impl)
    • within(cn.tedu.cloudnote.service.UserServiceImpl)
    • within(cn.tedu.cloudnote..Impl)
  3. execution方法切入点 execution(执行)
    • 语法: execution(修饰词 方法全名(参数列表))
    • execution(* cn.tedu.cloudnote.service.UserService.login(..))
    • execution(* cn.tedu.cloudnote.service.UserService.*(..))
    • execution(* cn.tedu.cloudnote..Service.(..))

建议: 切入点位置有接口! 如果切入位置有接口 AspectJ 会利用JDK动态代理实现织入, 如果没有接口, 则使用CGLIB动态代理织入.

AOP ServletFilter 拦截器 区别

都是横切编程

  1. ServletFilter 是Servlet的标准, 适合于Web请求拦截
  2. 拦截器是SpringMVC提供的组件, 适合拦截处理SpringMVC请求流程
  3. AOP 是Spring 容器提供的功能, 适合拦截Spring容器中管理的Bean

根据拦截位置不同选择不同的拦截器编程方式.

事务编程

回顾编程式事务处理:

try{打开连接开始事务事务操作1事务操作2事务操作3提交事务
}catch(Exception e){回滚事务
}fianlly{回收资源,关闭连接
}

使用编程式事务处理, 代码冗长繁琐.

Spring利用AOP机制实现了声明式事务处理, 在业务代码中使用事务注解即可以处理事务, 不需要写复杂的事务处理代码!

声明式事务处理使用步骤:

  1. 配置事务管理器 spring-mybatis.xml:

    <!-- 配置事务管理器 -->
    <bean id="txManager"                class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dbcp"/>
    </bean><!-- 用于支持 @Transactional 注解 必须配置事务管理器属性, 其值是一个Bean的ID-->
    <tx:annotation-driven transaction-manager="txManager"/>
    
  2. 在业务方法上使用 事务注解 UserServiceImpl.java:

    @Transactional
    public User login(String name, String password) throws NameException, PasswordException {//参数格式校验if(name==null || name.trim().isEmpty()){throw new NameException("用户名不能为空");}if(password==null || password.trim().isEmpty()){throw new PasswordException("密码不能为空");}//密码检验User user=userDao.findUserByName(name);if(user==null){throw new NameException("用户名错误");}//Thread t = Thread.currentThread();//System.out.println(t); //String s = null;//s.length();String md5Password=NoteUtil.md5(password);if(user.getPassword().equals(md5Password)){return user;}else{throw new PasswordException("密码错误");}
    }
    

注意: MySQL的MyISAM数据库引擎,不支持ACID(不能回滚), InnoDB 支持ACID

事务处理案例, 批量删除笔记:

原理:

步骤:

  1. 声明数据层方法 NoteDao.java:

    int deleteNoteById2(String id);
    
  2. 添加SQL语句 NoteMapper.xml:

    <delete id="deleteNoteById2"parameterType="string">delete from cn_note where cn_note_id = #{id}
    </delete>
    
  3. 添加业务层接口 NoteService.java:

    int deleteNotes(String... ids);
    
  4. 实现业务层方法 NoteServiceImpl.java:

    @Transactional
    public int deleteNotes(String... ids) {int n = 0;for (String id : ids) {int i=noteDao.deleteNoteById2(id);if(i==0){throw new RuntimeException("id是错误的"+id);}n+=i;}return n;
    }
    

    在业务方法出现异常时候, 会引起事务回滚.

  5. 测试 TesrNoteService.java:

    @Test
    public void testDeleteNotes(){// 84b2d98b-af39-4655-8aa8-d8869d043cca// c347f832-e2b2-4cb7-af6f-6710241bcdf6// 07305c91-d9fa-420d-af09-c3ff209608ff// 5565bda4-ddee-4f87-844e-2ba83aa4925fString id1="84b2d98b-af39-4655-8aa8-d8869d043cca";String id2="c347f832-e2b2-4cb7-af6f-6710241bcdf6";String id3="07305c91-d9fa-420d-af09-c3ff209608ff";String id4="5565bda4-ddee-4f87-844e-2ba83aa4925f";noteService.deleteNotes(id1,id2,id3,id4);
    }
    

测试结果: 发生异常时候回滚初始状态.


作业:

  1. 利用AOP实现性能测试功能, 输出每个业务层方法的执行耗费时间
  2. 为云笔记软件业务层添加事务, 并且测试出现异常时候是否发生回滚操作

spring-AOP-苍老师相关推荐

  1. spring aop实例讲解_Spring框架核心知识点

    文章内容输出来源:拉勾教育Java高薪训练营 前言: 由于工作需要提升自身技术能力,在各方比较下,报名了拉勾教育的java高薪训练营,目前已经学了半个月啦,来说说自身学习的感受吧: 课程内容有广度更有 ...

  2. mysql aop_aop: 使用spring aop实现业务层mysql 读写分离

    使用spring aop实现业务层mysql 读写分离 现在大型的电子商务系统,在数据库层面大都采用读写分离技术,就是一个Master数据库,多个Slave数据库.Master库负责数据更新和实时数据 ...

  3. spring aop获取目标对象的方法对象(包括方法上的注解)(转)

    这两天在学习权限控制模块.以前看过传智播客黎活明老师的巴巴运动网视频教程,里面就讲到权限控制的解决方案,当时也只是看看视频,没有动手实践,虽说看过几遍,可是对于系统中的权限控制还是很迷茫,所以借着这次 ...

  4. Spring AOP理论 +代理模式详解

    目录 1.理解AOP 1.1.什么是AOP 1.2.AOP体系与概念 1.3.Spring AOP 通知的执行顺序 2.代理模式 2.1.静态代理 2.2.静态代理的缺点 3.动态代理 JDK 动态代 ...

  5. Spring AOP + Redis解决重复提交的问题

    Spring AOP + Redis解决重复提交的问题 用户在点击操作的时候,可能会连续点击多次,虽然前端可以通过设置按钮的disable的属性来控制按钮不可连续点击,但是如果别人拿到请求进行模拟,依 ...

  6. 利用Spring AOP与JAVA注解为系统增加日志功能

    Spring AOP一直是Spring的一个比较有特色的功能,利用它可以在现有的代码的任何地方,嵌入我们所想的逻辑功能,并且不需要改变我们现有的代码结构. 鉴于此,现在的系统已经完成了所有的功能的开发 ...

  7. Spring AOP的一些概念

            切面(Aspect): 一个关注点的模块化,这个关注点可能会横切多个对象.事务管理是J2EE应用中一个关于横切关注点的很好的例子. 在Spring AOP中,切面可以使用通用类(基于模 ...

  8. Spring AOP与IOC

    Spring AOP实现日志服务 pom.xml需要的jar <dependency><groupId>org.apache.commons</groupId>&l ...

  9. Spring AOP与IOC以及自定义注解

    Spring AOP实现日志服务 pom.xml需要的jar <dependency><groupId>org.apache.commons</groupId>&l ...

  10. Spring Aop的应用

    2019独角兽企业重金招聘Python工程师标准>>> AOP的基本概念 连接点( Jointpoint) : 表示需要在程序中插入横切关注点的扩展点,连接点可能是类初始化.方法执行 ...

最新文章

  1. Linux 3D 编程学习总结
  2. linux实验串行端口程序设计,Linux下串口编程心得(转)
  3. python参数_python 参数
  4. 新兴的多媒体格式——MXF 文件格式分析 和简介
  5. 1万亿次、10亿人、10亿张,科技给生活带来多少改变?
  6. php订阅与推送,PHP用户关键词订阅推送文章功能
  7. SpringMVC中使用@RequestBody,@ResponseBody注解实现Java对象和XML/JSON数据自动转换)
  8. Java集合List,Set,Map,Queue,Deque
  9. 邮件作为证据如何提交_电子邮件如何取证、举证?
  10. 仿摩拜单车APP(包括附近车辆、规划路径、行驶距离、行驶轨迹记录,导航等)...
  11. 薛兆丰经济学讲义 简述
  12. 闹钟Android实验报告,单片机实验报告(闹钟).doc
  13. win10计算机图标怎么放桌面壁纸,win10系统桌面图标显示和背景修改的具体方法...
  14. JSON (JavaScript Object Notation)
  15. oracle 中 的 =,oracle中=是什么意思
  16. 2015年第4本(英文第3本):Godfather教父
  17. Bootstrap第一章初识
  18. Centos系统找出并杀死僵尸进程
  19. Hazel引擎学习(四)
  20. Z-STACK之cc2530LED驱动详解

热门文章

  1. 亲自操作,有用的win10遇到“已禁用输入法”无法启动中文输入法的问题-提示已禁用输入法解决方案
  2. WinForm实现倒计时锁定程序完整源码附注释
  3. /home/image/.conda/envs/tensorflow/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py
  4. oracle重做control,Oracle 通过Database Control 向重做日志组中添加成员
  5. 神经网络 和 NLP —— 语言模型和词向量
  6. 科技爱好者周刊(第 160 期):中年码农的困境
  7. Android深入浅出系列课程---Lesson15LLY110602_Dalvik虚拟机概述
  8. 无心剑汉英双语诗003. 《书海》
  9. 计算机考试机试题目word文档,计算机考试 word
  10. Python批量处理lrmx格式文档内指定内容