Spring中整合了AOP的功能,虽然有不足,没有专门做AOP框架的那么完美,但是用一用感觉还是不错的

一些概念:

AOP 面向切面编程

aspect 切面/切面类(我个人认为一个真正被解耦的程序,切面类中的功能可以切入到 任何一个目标类中 无所谓是service层或者说是dao层中的类)

joinPoint 连接点

在spring的aop中只有 类中的方法 可以做连接点,每一个方法都可以是一个连接点.

pointCut 切入点

一组连接点的集合

advice 通知/拦截器

用来控制切面类将来到底是织入到切入点的前面、后面或者是抛异常的时候。

adivsor 增强器
用来筛选类中的哪些方法是我们的连接点(哪些方法需要被拦截).

target 目标对象

proxy 代理对象

wave 织入

-----------------------

advice(通知)的类型:

前置通知(Before advice):
在某些连接点(join point)之前执行的通知

返回后通知(After returning advice):
在某些连接点(join point)正常完成后执行的通知(方法正常结束,没有异常)

抛出异常后通知(After throwing advice):
在某些连接点(join point)抛出异常退出时执行的通知

后通知(After (finally) advice):
当某些连接点(join point)退出的时候执行的通知

环绕通知(Around Advice):
包围一个连接点(join point)的通知,例如事务的处理,就需要这样的通知,因为事务需要在方法前开启,在方法后提交,以及方法抛出异常时候回滚

注:在spring中,连接点(join point)指的就是方法

Spring中提供了AOP的实现方式 在XMl中配置只需要三步就可以实现

1.配置目标类
2.配置拦截器(配置切面类【可选】)
3.配置代理对象

配置xml文件:

1.首先是配置目标类

<!-- 配置dao层对象 -->
<bean id="dao" class="com.briup.aop.dao.AccountDaoImpl"/> <!-- 配置一个测试账户 -->
<bean name="account" class="com.briup.aop.pojo.Account">
<property name="id" value="1"></property>
<property name="name" value="tom"></property>
<property name="balance" value="1000"></property>
</bean> <!-- 配置目标对象 -->
<bean name="target"
class="com.briup.aop.service.AccountServiceImpl">
<property name="accountDao" ref="dao"></property>
<property name="account" ref="account"></property>
</bean>

2.配置拦截器

<!-- 配置切面类 -->
<bean name="logger" class="com.briup.aop.aspect.MyLogger"></bean> <!-- 配置advice -->
<bean name="beforeAdvice" class="com.briup.aop.before.BeforeAdvice">
<!-- 注入切面类对象 -->
<property name="logger" ref="logger"></property>
</bean>

3.配置代理对象

<!-- 这里使用的是spring的一个代理对象工厂类产生的 -->
<bean name="proxy"
class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 注入目标对象 -->
<property name="target" ref="target"></property> <!-- 注入目标对象所实现的接口 可以有多个接口 -->
<!-- 注入代理类需要实现的接口 代理类实现接口与目标类实现接口相同 -->
<property name="proxyInterfaces">
<list>
<value>com.briup.aop.service.IAccountService</value>
</list>
</property> <!-- 注入advice 可以有多个 -->
<property name="interceptorNames">
<list>
<value>beforeAdvice</value>
</list>
</property> </bean>

这样配置有三个问题:
1.这个目标类对应接口下的方法都被加入了功能
2.需要为每一个目标类进行配置
3.目标类必须实现接口

首先我们解决第一个问题
我们的Spring中提供了advisor(增强器),增强器包装了一下advice(拦截器),可以筛选向接口中的那个方法添加功能

1.首先是配置目标类

<!-- 配置dao层对象 -->
<bean id="dao" class="com.briup.aop.dao.AccountDaoImpl"/> <!-- 配置一个测试账户 -->
<bean name="account" class="com.briup.aop.pojo.Account">
<property name="id" value="1"></property>
<property name="name" value="tom"></property>
<property name="balance" value="1000"></property>
</bean>
<!-- 配置目标对象 -->
<bean name="target"
class="com.briup.aop.service.AccountServiceImpl">
<property name="accountDao" ref="dao"></property>
<property name="account" ref="account"></property>
</bean>

2.配置拦截器

<!-- 配置切面类 -->
<bean name="logger" class="com.briup.aop.aspect.MyLogger"></bean> <!-- 配置advice -->
<bean name="beforeAdvice" class="com.briup.aop.before.BeforeAdvice">
<!-- 注入切面类对象 -->
<property name="logger" ref="logger"></property>
</bean>

3.添加增强器

<!-- 配置advisor 增强器-->
<!-- 作用:筛选要拦截(要代理)的方法 -->
<bean name="advisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!-- 注入advice-->
<property name="advice" ref="beforeAdvice"></property>
<!-- 注入需要被拦截的目标对象中的方法(连接点) -->
<property name="patterns">
<list>
<value>.*bankAction</value> <!--单个字符出现0到多次-->
</list>
</property>
</bean>
<!--RegexpMethodPointcutAdvisor默认的正则表达式选择方法-->
<!--NameMatchMethodPointcutAdvisor按照方法名匹配-->

4.配置代理对象

<!-- 这里使用的是spring的一个代理对象工厂类产生的 -->
<bean name="proxy"
class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- 注入目标对象 -->
<property name="target" ref="target"></property> <!-- 注入目标对象所实现的接口 可以有多个接口 -->
<!-- 注入代理类需要实现的接口 代理类实现接口与目标类实现接口相同 -->
<property name="proxyInterfaces">
<list>
<value>com.briup.aop.service.IAccountService</value>
</list>
</property> <!-- 注入advice/advisor 可以有多个 -->
<property name="interceptorNames">
<list>
<value>advisor</value>
</list>
</property>
</bean>

我们处理了第一个问题,被处理的方法可以指定了

我们开始解决第二个问题
自动的进行配置:自动代理:DefaultAdvisorAutoProxyCreator类的使用

xml配置文件:

1.配置拦截器

<!-- 配置切面类 -->
<bean name="logger" class="com.briup.aop.aspect.MyLogger"></bean> <!-- 配置advice -->
<bean name="beforeAdvice"
class="com.briup.aop.before.BeforeAdvice">
<!-- 注入切面类对象 -->
<property name="logger" ref="logger"></property>
</bean>

2.添加增强器

<!-- 配置advisor -->
<!-- 作用:筛选要拦截的方法 -->
<bean name="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!-- 注入advice -->
<property name="advice" ref="beforeAdvice"></property>
<!-- 注入需要被拦截的目标对象中的方法 -->
<property name="patterns">
<list>
<value>.*bankAction</value>
</list>
</property>
</bean>

配置目标对象,这里的对象中只要有增强器中的方法,就可以当作代理对象,Cgilb代理默认的将含有增强器中的方法的
所有对象都进行了处理,比如以下这个target对象,从容器中拿出后就是加入了功能的了,但是这些对象得要放在一个容器下面

在Spring中最需要注意的就是对象在不在容器中,对象不在容器中就没办法受到Spring框架的控制了

<bean name="target"
class="com.briup.aop.service.AccountServiceImpl">
</bean>

3.实现自动代理

<!-- 配置代理对象 -->
<!-- 这里使用自动代理的方式 autoproxy -->
<!-- 注意:这不是一个工厂类,所以不能用过proxy来拿代理对象 -->
<bean name="proxy"
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
</bean>

这样做就可以自动的对需要功能的方法进行代理处理了,也不用实现接口了

使用自动代理的时候需要注意的方面:
1.当前的配置里面"一定要有"一个advisor的配置
2.不需要向自动代理类中注入任何信息
3.不管目标对象是否实现了一个或多接口,自动代理的方式都能够为它产生代理对象(CGLib的方式).
4.从spring容器中拿代理对象的时候,需要通过目标对象的名字来拿。
5.spring如何确定配置文件中哪个bean是作为目标对象:
通过advisor中筛选的方法,如果这个bean中含有advisor中所配置的方法,则这个bean将来称为我们的目标对象进行代理

但是又有问题来了:
我们对所有含有同名方法的类对象进行了处理,如果想为指定类对象中的方法进行处理呢?

Spring同样进行了处理:

通过名字进行自动代理:BeanNameAutoProxyCreator类的使用

xml配置文件:

1.配置拦截器

<!-- 配置切面类 -->
<bean name="logger" class="com.briup.aop.aspect.MyLogger"></bean>
<!-- 配置advice -->
<bean name="beforeAdvice"
class="com.briup.aop.before.BeforeAdvice">
<!-- 注入切面类对象 -->
<property name="logger" ref="logger"></property>
</bean>

2.添加增强器

<!-- 配置advisor -->
<!-- 作用:筛选要拦截的方法 -->
<bean name="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!-- 注入advice -->
<property name="advice" ref="beforeAdvice"></property>
<!-- 注入需要被拦截的目标对象中的方法 -->
<property name="patterns">
<list>
<value>.*bankAction</value>
</list>
</property>
</bean>

<!-- 配置目标对象 -->

<bean name="target" class="com.briup.aop.service.AccountServiceImpl"> </bean>

<bean name="target2" class="com.briup.aop.service.AccountServiceImpl"> </bean>

<bean name="target3" class="com.briup.aop.service.AccountServiceImpl"></bean>

3.实现自动代理

<!-- 配置代理对象 -->
<!-- 这里使用自动代理的方式 autoproxybyname -->
<bean name="proxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<!-- 注入需要被代理的对象名字 -->
<property name="beanNames">
<list>
<value>target</value>
<value>target2</value>
<value>dao</value>
<value>service*</value>
</list>
</property> <!-- 注入advice或者advisor -->
<property name="interceptorNames">
<list>
<value>advisor</value>
</list>
</property>
</bean>

使用byName自动代理的时候需要注意的方面:
1.当前的配置里面"有没有"advisor的配置"都没关系"
有advisor可以精确选择加强功能的方法,没有就是类中的所有方法了

2.需要向自动代理类中注入被代理目标对象的名字已经advice或者advisor
就是说advisor中指定的方法在 被代理目标对象 中存在

3.不管目标对象是否实现了一个或多接口,自动代理的方式都能够为它产生代理对象.

4.从spring容器中拿代理对象的时候,需要通过目标对象的名字来拿。
这一点在DefaultAdvisorAutoProxyCreator的使用中就说过了
可以说 目标对象加入了功能,变成了代理对象

Spring中封装了AspectJ
所以我们也可以使用到这种框架的功能了,Spring中提供了aop:config标签,使用aop的专用标签来完成相关的配置.这个标签我也是正在研究,据说挺好用的☺。

最新文章

  1. SQL Server 数据库子查询基本语法
  2. Memcache学习整理
  3. android 基础控件 EditText
  4. JavaScript高级程序设计之JSON
  5. FluorineFx对于现有站点的配置
  6. JavaScript权威指南学习笔记4
  7. Xcoder 7.0 免证书真机测试
  8. 采用truelicense进行Java规划license控制 扩展可以验证后,license 开始结束日期,验证绑定一个给定的mac住址
  9. 去除win7 64位系统桌面图标小箭头
  10. windows下grunt安装提示不成功
  11. poptest老李谈分布式与集群
  12. geotools实现多边形的合并&amp;缓冲区
  13. java设计模式---备忘录模式
  14. vue发送请求---fetch-jsonp
  15. How to create your iOS team provisioning profile ?
  16. Linux伙伴算法
  17. 统计SQL Server所有表记录数
  18. Spring整合MyBatis(五)MapperScannerConfigurer
  19. cocos2d-x分别在Visual Studio和eclipse中设置启用Box2D
  20. JS 根据url 下载

热门文章

  1. Vue开发实战
  2. HTML中的相对路径与绝对路径
  3. 在线暴躁:&lt;script /&gt;问题
  4. 全球首个开放应用模型 OAM 开源
  5. 显示所有用户,mysql的基本操作
  6. NX二次开发-对话框解锁UF_UI_unlock_ug_access
  7. macOS cataline 10.15 升级后问题一览
  8. 简单HOOK SSDT实现文件防删除
  9. class1and2_tkinter之 Label &amp; Button 标签和按钮
  10. 网页开发人员收藏的16款HTML5工具