上一章:[Spring+SpringMVC+Mybatis]框架学习笔记(四):Spring实现AOP

下一章:[Spring+SpringMVC+Mybatis]框架学习笔记(六):Spring_AspectJ实现AOP

第5章 SpringAOP_顾问

对第4章Spring实现AOP的缺点的思考:

  • 一个代理只能代理一个bean,意味着在实际应用中要定义多个代理;(通过默认advisor自动代理生成器来解决)
  • 从容器中获取对象是通过代理的bean的id,而不是我们在容器中定义的目标对象的id;(通过默认advisor自动代理生成器来解决)
  • 通知只能切入到目标类的所有的方法,不能指定某些方法。(通过顾问对通知的封装实现)

5.1 顾问Advisor

它将通知进行了包装,根据通知的不同类型,在不同的时间点,将切面织入到指定的目标对象的某些连接点。

PointCutAdvisor 顾问的一种,它是一个接口,有两个实现类:

  • NameMatchMethodPointCutAdvisor 名称匹配方法切入点顾问
  • RegexpMethodPointCutAdvisor 正则表达式方法切入点顾问

复习正则表达式:

(*) 星号:匹配前面的子表达式任意次 例如:ao* 能匹配 a ao aoo aooooo

(+) 加号:匹配前面的子表达式一次或多次 例如:ao+ 能匹配 ao aoo aooooo

(.) 点 :匹配任意字符 除“\r\n”之外

.* 代表任意的一个字符串 .*add.* 代表包含add字符的任意字符串

实例:

利用实例4.5的目标类接口、目标类、通知,实现切入到目标类的指定的方法。

1)配置文件

<?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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 注册服务类,并描述依赖关系 -->
<bean id="studentService" class="com.steven.spring.sysmgr.service.impl.StudentService"></bean> <!-- 注册前置通知 -->
<bean id="beforeAdvice" class="com.steven.spring.sysmgr.advice.MyBeforeAdvice"></bean> <!-- 注册后置通知 -->
<bean id="afterAdvice" class="com.steven.spring.sysmgr.advice.MyAfterAdvice"></bean> <!-- 注册环绕通知 -->
<bean id="aroundAdvice" class="com.steven.spring.sysmgr.advice.MyAroundAdvice"></bean> <!-- 注册异常通知 -->
<bean id="throwingAdvice" class="com.steven.spring.sysmgr.advice.MyThrowingAdvice"></bean> <!-- 注册一个名称匹配方法切入点顾问 -->
<!-- 顾问Advisor比通知Advice多了一个指定方法的步骤 -->
<bean id="beforeAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice" ref="beforeAdvice"/>
<!-- 限定单个目标方法 -->
<property name="mappedName" value="addStudent"/>
<!-- 限定多个目标方法 -->
<!-- 方法1 -->
<!-- <property name="mappedNames" value="addStudent,updateStudent"/> -->
<!-- 方法2 -->
<!-- <property name="mappedNames">
<array>
<value>addStudent</value>
<value>updateStudent</value>
</array>
</property> -->
<!-- 方法3 -->
<!-- <property name="mappedNames" value="*Student"/> --> </bean> <!-- 注册前置顾问代理生成器 -->
<bean id="myBeforeAdvisorProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="studentService"/>
<property name="interceptorNames" value="beforeAdvisor"/>
</bean> <!-- 注册一个正则表达式方法切入点顾问 -->
<bean id="afterAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="afterAdvice"/>
<!--限定单种方法-->
<property name="pattern" value=".*add.*"/>
<!-- 限定多种 -->
<property name="patterns" value=".*add.*,.*del.*"/>
</bean> <!-- 注册后置顾问代理生成器 -->
<bean id="myAfterAdvisorProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="studentService"/>
<property name="interceptorNames" value="afterAdvisor"/>
</bean> </beans>

2)测试

package com.steven.spring.sysmgr.test;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.steven.spring.sysmgr.entity.Student;
import com.steven.spring.sysmgr.service.IStudentService; /**
* 测试顾问
* @author chenyang
*
*/
public class AdvisorTest {
private ApplicationContext ac = null; @Before
public void init(){
ac = new ClassPathXmlApplicationContext("applicationContext.xml");
} //测试前置顾问,指定某些方法,使用名称匹配切入点方法顾问来实现
@Test
public void testBeforeAdvisor(){
IStudentService studentService = (IStudentService) ac.getBean("myBeforeAdvisorProxy");
studentService.addStudent(new Student());
studentService.updateStudent(new Student());//修改功能的前置通知不能被打印
} //测试后置顾问,指定某些方法,使用正则表达式切入点方法顾问来实现
@Test
public void testAfterAdvisor(){
IStudentService studentService = (IStudentService)ac.getBean("myAfterAdvisorProxy");
studentService.addStudent(new Student());
studentService.delStudent(1);
studentService.updateStudent(new Student());
} }

5.2 自动代理生成器

Spring提供了自动代理生成器来解决要定义多个代理生成器的问题,有两种方式:

  • 默认advisor自动代理生成器(目标对象为配置文件中配置的所有的目标对象bean,而且为配置文件里面所有的advisor自动生成代理); ---> 笼统
  • bean名称自动代理生成器(可以指定某些目标对象(bean),而且可以指定某些切面的实现(advise/advisor)) 。 ---> 精确

总结:

第4-5章中各种技术的运用,无非是为了一个目标:将我们编写的切面的实现(通知/顾问)织入到某些类的某些方法中。

实例:

利用实例4.5的目标类接口、目标类、通知,实现切入到目标类的指定的方法。

1)配置文件

<?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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 注册服务类,并描述依赖关系 -->
<bean id="studentService" class="com.steven.spring.sysmgr.service.impl.StudentService"></bean> <!-- 注册前置通知 -->
<bean id="beforeAdvice" class="com.steven.spring.sysmgr.advice.MyBeforeAdvice"></bean> <!-- 注册后置通知 -->
<bean id="afterAdvice" class="com.steven.spring.sysmgr.advice.MyAfterAdvice"></bean> <!-- 注册环绕通知 -->
<bean id="aroundAdvice" class="com.steven.spring.sysmgr.advice.MyAroundAdvice"></bean> <!-- 注册异常通知 -->
<bean id="throwingAdvice" class="com.steven.spring.sysmgr.advice.MyThrowingAdvice"></bean> <!-- 注册一个名称匹配方法切入点顾问 -->
<!-- 顾问Advisor比通知Advice多了一个指定方法的步骤 -->
<bean id="beforeAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice" ref="beforeAdvice"/>
<property name="mappedName" value="addStudent"/>
</bean> <!-- 注册一个正则表达式方法切入点顾问 -->
<bean id="afterAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="afterAdvice"/>
<property name="pattern" value=".*add.*"/>
</bean> <!-- 默认Advisor自动代理生成器,目标对象为配置文件中注册的所有的目标对象,advisor为配置文件中所有的advisor -->
<!-- <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean> --> <!-- bean名称自动代理生成器,不仅可以指定目标对象,还可以指定advise/advisor(注意:这里都可以!) -->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="studentService"/>
<property name="interceptorNames" value="beforeAdvisor"/>
</bean> </beans>

2)测试默认Advisor自动代理生成器

package com.steven.spring.sysmgr.test;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.steven.spring.sysmgr.entity.Student;
import com.steven.spring.sysmgr.service.IStudentService; public class DefaultAdvisorAutoProxyCreator {
private ApplicationContext ac = null; @Before
public void init(){
ac = new ClassPathXmlApplicationContext("applicationContextForAutoProxy.xml");
} //测试默认顾问自动代理生成器
@Test
public void testDefaultAdvisorAutoProxyCreator(){
// 注意:这里是直接取容器中定义的目标对象的id,不再使用代理生成器的id
IStudentService studentService = (IStudentService) ac.getBean("studentService");
studentService.addStudent(new Student());
studentService.updateStudent(new Student());//修改功能的前置通知不能被打印
}
}

3)测试bean名称自动代理生成器

package com.steven.spring.sysmgr.test;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.steven.spring.sysmgr.entity.Student;
import com.steven.spring.sysmgr.service.IStudentService; public class BeanNameAutoProxyCreator {
private ApplicationContext ac = null; @Before
public void init(){
ac = new ClassPathXmlApplicationContext("applicationContextForAutoProxy.xml");
} //测试bean名称自动代理生成器
@Test
public void testBeanNameAutoProxyCreator(){
IStudentService studentService = (IStudentService) ac.getBean("studentService");
studentService.addStudent(new Student());
studentService.updateStudent(new Student());
}
}

上一章:[Spring+SpringMVC+Mybatis]框架学习笔记(四):Spring实现AOP

下一章:[Spring+SpringMVC+Mybatis]框架学习笔记(六):Spring_AspectJ实现AOP

[Spring+SpringMVC+Mybatis]框架学习笔记(五):SpringAOP_顾问的更多相关文章

  1. [Spring+SpringMVC+Mybatis]框架学习笔记(六):事务

    第7讲 事务 7.1 事务的概念 事务是一系列作为一个逻辑单元来执行的操作集合. 它是数据库维护数据一致性的单位,它讲数据库从一个一致状态,转变为新的另外一个一致状态.说的简单一点就是:如果一组处理步 ...

  2. Spring+SpringMVC+MyBatis集成学习笔记【一】

    一,首先要清楚,SpringMVC其实就是Spring的一个组件       例如我们知道Spring中有类似于,AOP TX等等类似的组件,所以SpringMVC其实就是Spring的一个组件,是S ...

  3. Spring+SpringMVC+MyBatis深入学习及搭建(五)——动态sql

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6908763.html 前面有讲到Spring+SpringMVC+MyBatis深入学习及搭建(四)——My ...

  4. Spring+SpringMVC+MyBatis深入学习及搭建(十五)——SpringMVC注解开发(基础篇)

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7065294.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(十四)--S ...

  5. Spring+SpringMVC+MyBatis深入学习及搭建(十六)——SpringMVC注解开发(高级篇)

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7085268.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(十五)——S ...

  6. Spring+SpringMvc+Mybatis框架集成搭建教程

    一.背景 最近有很多同学由于没有过SSM(Spring+SpringMvc+Mybatis , 以下简称SSM)框架的搭建的经历,所以在自己搭建SSM框架集成的时候,出现了这样或者那样的问题,很是苦恼 ...

  7. Spring+SpringMVC+MyBatis深入学习及搭建(二)——MyBatis原始Dao开发和mapper代理开发

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6869133.html 前面有写到Spring+SpringMVC+MyBatis深入学习及搭建(一)——My ...

  8. Spring+SpringMVC+MyBatis深入学习及搭建(三)——MyBatis全局配置文件解析

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6874672.html 前面有写到Spring+SpringMVC+MyBatis深入学习及搭建(二)——My ...

  9. Spring+SpringMVC+MyBatis深入学习及搭建(六)——MyBatis关联查询

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6923464.html 前面有将到:Spring+SpringMVC+MyBatis深入学习及搭建(五)--动 ...

  10. Spring+SpringMVC+MyBatis深入学习及搭建(八)——MyBatis查询缓存

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6956206.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(七)——My ...

随机推荐

  1. 31-dll

    webpack.dll.js /** * 使用dll技术,对某些库(第三方库:jquery.react.vue...)进行单独打包 * 当你运行 webpack 时,默认查找 webpack.conf ...

  2. [Pytorch框架] 5.3 Fashion MNIST进行分类

    文章目录 5.3 Fashion MNIST进行分类 Fashion MNIST 介绍 数据集介绍 分类 格式 数据提交 数据加载 创建网络 损失函数 优化器 开始训练 训练后操作 可视化损失函数 保 ...

  3. 音视频八股文(7)-- 音频aac adts三层结构

    AAC介绍 AAC(Advanced Audio Coding)是一种现代的音频编码技术,用于数字音频的传输和存储领域.AAC是MPEG-2和MPEG-4标准中的一部分,可提供更高质量的音频数据,并且 ...

  4. Django-账户用户忘记密码

    方法1:Terminal命令 python manage.py changepassword admin Password: PY666666 Password (again): PY666666 方 ...

  5. [学习笔记]解决因C#8.0的语言特性导致EFCore实体类型映射的错误

    今天下午在排查一个EF问题时,遇到了个很隐蔽的坑,特此记录. 问题 使用ef执行Insert对象到某表时报错,此对象的Address为空: 不能将值 NULL 插入列 'Address',表 'dbo ...

  6. 理论+实操,带你了解多沙箱容器运行时Kuasar

    摘要:华为云DTSE技术布道师张天阳结合沙箱容器发展历程,介绍华为云多沙箱容器运行时 Kuasar 项目优势,开启多沙箱容器运行时上手实践体验. 本文分享自华为云社区<理论+实操,带你了解多沙箱 ...

  7. ESlint配置详解

    开发中出现eslint提示代码格式错误,有时候不明白其配置规范,是件很头疼的事情到处找api又是半天:so记录一份配置详情便于开发中翻阅 { // 环境定义了预定义的全局变量. "env&q ...

  8. NLM 公布了一个新的重新设计的 PubMed 数据库

    经常使用 PubMed 的童鞋可能已经发现,美国国家医学图书馆(NLM)在今年 10 月份左右发布了一个新的重新设计的版本以取代 PubMed 数据库的现有版本,新版本现在已经上线,可以通过下面的链接 ...

  9. 文盘Rust -- tokio绑定cpu实践

    tokio 是 rust 生态中流行的异步运行时框架.在实际生产中我们如果希望 tokio 应用程序与特定的 cpu core 绑定该怎么处理呢?这次我们来聊聊这个话题. 首先我们先写一段简单的多任务 ...

  10. CompTIA Pentest+

    关于学习后CompTIA Pentest+笔记 渗透测试工具 讲述了nmap,burp Suite,Metasploit,Nessus,hydra的入门使用 nmap:https://www.cnbl ...