上一章:[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. Go语言实现分布式对象存储系统

    实现一个可扩展的,简易的,分布式对象存储系统 存储系统介绍 先谈谈传统的网络存储,传统的网络存储主要分为两类: NAS,即Newtwork Attached Storage,是一个提供了存储功能和文件 ...

  2. Qt第三方库QtAV--- ubuntu编译与运行

    Qt第三方库QtAV--- ubuntu编译与运行 今天又要接触这个,把一些错误或者不足的地方重新补充下!!!由于前面一段时间,项目中需要借助QtAV接口进行视频播放,特此记录下整个配置过程.整个代码 ...

  3. Pillow + pytesseract + tesseract-ocr 破解简单的图形验证码

    前言: 我们在做WEB UI自动化测试时,会遇到一些图形验证码,今天就来简单介绍下,如何来识别简单的图形验证码. 一.安装 ◇ Pillow pip3 install Pillow ◇ pytesse ...

  4. 基于ChatGPT用AI实现自然对话

    1.概述 ChatGPT是当前自然语言处理领域的重要进展之一,通过预训练和微调的方式,ChatGPT可以生成高质量的文本,可应用于多种场景,如智能客服.聊天机器人.语音助手等.本文将详细介绍ChatG ...

  5. 在C#中使用SQLite数据库

    轻量级桌面程序数据库不太适合用SQLServer.MySQL之类的重量级数据库,嵌入式数据库更好.在对比Access.SQLite.Firebird数据库后发现SQLite较另外两个有较多优点. 环境 ...

  6. Axure 手机页面拖动效果

    1.设置好上下固定们,中间放一个动态面板,如下图所示,(刚开始创建是没有图片的) 2.再状态1下再创建一个动态面板 命名为D2,如下图所示 3.在D2的状态1下新建一个宽370(大概手机宽)高1100 ...

  7. IPS 和 IDS

    IPS/IDS 什么是IPS和IDS IDS/IPS是检测和防止对网络服务器进行未授权的访问的系统.有许多产品同时有IDS和IPS的作用,作为加强企业信息安全所必须的系统 什么是IDS(Intrusi ...

  8. cat,more,cp,mv,rm,命令

    cat命令 查看文件内容 语法:cat[linux路径] more命令查看文件内容 more命令同样可以查看文件内容, 同cat不同的是: •cat是直接将内容全部显示出来 •more支持翻页,如果文 ...

  9. 2022-11-14:rust语言,请使用过程宏给结构体AAA生成结构体AAABuilder和创建AAABuilder实例的方法。 宏使用如下: #[derive(Builder)] pub stru

    2022-11-14:rust语言,请使用过程宏给结构体AAA生成结构体AAABuilder和创建AAABuilder实例的方法. 宏使用如下: #[derive(Builder)] pub stru ...

  10. <form>表单中的action和method使用方法

    <form action="" method="post"> form是表单   里面的内容是要提交出去的. action 是链接   点击浏览选择 ...