上一章:[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. ts中报错信息收集

    1. 错误代码 参考:https://www.mmbyte.com/article/92849.html 1 state.localuserInfo = JSON.parse(localStorage ...

  2. 如何实现Spring中服务关闭时对象销毁执行代码

    spring提供了两种方式用于实现对象销毁时去执行操作 1.实现DisposableBean接口的destroy 2.在bean类的方法上增加@PreDestroy方法,那么这个方法会在Disposa ...

  3. [UR #14]人类补完计划

    计数好题. 题意:给定简单无向图 \(G=(V,E),|V|=n,|E|=m\),有 \(n\leq 16,m\leq {n\choose 2}\),求所有为基环树的子图的权值之和.一个基环树的权值定 ...

  4. 百度飞桨(PaddlePaddle)- 张量(Tensor)

    飞桨 使用张量(Tensor) 来表示神经网络中传递的数据,Tensor 可以理解为多维数组,类似于 Numpy 数组(ndarray) 的概念.与 Numpy 数组相比,Tensor 除了支持运行在 ...

  5. 2021-03-20:给定一个二维数组matrix,其中的值不是0就是1,返回全部由1组成的子矩形数量。

    2021-03-20:给定一个二维数组matrix,其中的值不是0就是1,返回全部由1组成的子矩形数量. 福大大 答案2021-03-20: 按行遍历二维数组,构造直方图. 单调栈,大压小.有代码. ...

  6. Matplotlib.pyplot.plot 绘图

    Matplotlib.pyplot 创建图形.在图形中创建创建一个绘图区域.在绘图区域中你那个绘制一些线.在图形中添加标签之类 画二维平面图 x = np.arange(0, 10, 2) y1 = ...

  7. Java中synchronized的优化

    本文介绍为了实现高效并发,虚拟机对 synchronized 做的一系列的锁优化措施 高效并发是从 JDK5 升级到 JDK6 后一项重要的改进项,HotSpot 虚拟机开发团队在 JDK6 这个版本 ...

  8. java解决中文乱码的几种写法

    工作中总会遇到中文乱码问题,以导出文件,文件名称是中文的话,下载下来的文件名称会乱码问题,总结了几种解决文件名乱码的写法,仅供参考. 首先定义一个汉语字符串 String zhName = " ...

  9. HTML渲染机制

    一直写页面但是很少对一些较深的运行机制的了解,这次趁休假查了一些相关的资料加上个人理解,记录一下关于html渲染的整个过程,也加深一下自己对html渲染的理解 一.先借一张图来看看html的整个加载过 ...

  10. Vue3.3 的新功能的体验(下):泛型组件(Generic Component) 与 defineSlots

    上一篇说了 DefineOptions.defineModel.Props 的响应式解构和从外部导入类型 这几个新功能,但是没有说Generic.defineSlots等,这是因为还没有完全搞清楚可以 ...