[Spring中的通知(Advice)和顾问(Advisor)]

Spring中的通知(Advice)和顾问(Advisor)

在Spring中,目前我学习了几种增强的方式,和大家分享一下

之前的话:

1.AOP (Aspect Oriented Programming 面向切面编程)

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

面向对象编程是从【静态角度】考虑程序的结构,而面向切面编程是从【动态角度】考虑程序运行过程。
AOP底层,就是采用【动态代理】模式实现的。采用了两种代理:JDK动态代理和CGLIB动态代理。

基本术语(一些名词):
(1)切面(Aspect)
切面泛指[交叉业务逻辑]。事务处理和日志处理可以理解为切面。常用的切面有通知(Advice)与顾问(Advisor)。实际就是对主业务逻辑的一种增强。

(2)织入(Weaving)
织入是指将切面代码插入到目标对象的过程。代理的invoke方法完成的工作,可以称为织入。

(3) 连接点(JoinPoint)
连接点是指可以被切面织入的方法。通常业务接口的方法均为连接点

(4)切入点(PointCut)
切入点指切面具体织入的方法
注意:被标记为final的方法是不能作为连接点与切入点的。因为最终的是不能被修改的,不能被增强的。

(5)目标对象(Target)
目标对象指将要被增强的对象。即包含主业务逻辑的类的对象。

(6)通知(Advice)
通知是切面的一种实现,可以完成简单的织入功能。通知定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是执行之后执行等。切入点定义切入的位置,通知定义切入的时间。

(7)顾问(Advisor)
顾问是切面的另一种实现,能够将通知以更为复杂的方式织入到目标对象中,是将通知包装为更复杂切面的装配器。

AOP是一种思想,而非实现
AOP是基于OOP,而又远远高于OOP,主要是将主要核心业务和交叉业务分离,交叉业务就是切面。例如,记录日志和开启事务。

一:前置增强和后置增强

image

源码介绍:

1.User.java

image

View Code

2.IDao.java

image

View Code

3.UserDao.java

image

View Code

4.IUserBiz.java

image

View Code

5.UserBiz.java

image

View Code

6.LoggerAfter.java(后置增强)

image

View Code

7.LoggerBefore.java(前置增强)

image

View Code

8.applicationContext.xml(Spring配置文件)

image

View Code

当然,针对AOP的配置也可以使用代理对象 ProxyFactoryBean 代理工厂bean来实现,在测试类中:IUserBiz biz=(IUserBiz)ctx.getBean("serviceProxy");

image

View Code

9.MyTest.java

image

View Code

10.log4j.properties(日志的配置文件)

image

View Code

当然,别忘了引入我们需要的jar包啊!

常用的jar:

image

二:异常抛出增强和环绕增强

image

源码介绍:

1.User.java

image

View Code

2.UserService.java

image

View Code

3.ErrorLog.java(异常抛出增强)

image

View Code

4.AroundLog(环绕增强)

image

View Code

5.applicationContext.xml(Spring配置文件)

image

View Code

6.MyTest.java

image

View Code

三:注解增强方式实现前置增强和后置增强

image

源码介绍:

1.UserService.java

image

View Code

2.AnnotationAdvice.java(注解增强)

image

View Code

注:

java.lang.Object[] getArgs():获取连接点方法运行时的入参列表
Signature getSignature() :获取连接点的方法签名对象
java.lang.Object getTarget() :获取连接点所在的目标对象
java.lang.Object getThis() :获取代理对象本身

3.applicationContext.xml(Spring配置文件)

image

View Code

4.MyTest.java

image

View Code

四: 顾问(Advisor)实现前置增强

通知Advice是Spring提供的一种切面(Aspect)。但其功能过于简单,只能
将切面织入到目标类的所有目标方法中,无法完成将切面织入到指定目标方法中。

顾问Advisor是Spring提供的另一种切面。其可以完成更为复杂的切面织入功能。PointcutAdvisor是顾问的一种,可以指定具体
的切入点。顾问将通知进行了包装,会根据不同的通知类型,在不同的时间点,将切面织入到不同的切入点。
PointcutAdvisor接口有两个较为常用的实现类:
:NameMatchMethodPointcutAdvisor 名称匹配方法切入点顾问
:RegexpMethodPointcutAdvisor 正则表达式匹配方法切入点顾问
<property name="pattern" value=".
do.
"></property> 表示方法全名(包名,接口名,方法名)
运算符 名称 意义
. 点号 表示任意单个字符

  • 加号 表示前一个字符出现一次或者多次
  • 星号 表示前一个字符出现0次或者多次
    =====默认Advisor自动代理生成器
    DefaultAdvisorAutoProxyCreator
    =====BeanName自动代理生成器
    BeanNameAutoProxyCreator

实例:

image

源码介绍:

1.ISomeService.java

image

[
复制代码

](javascript:void(0); "复制代码")

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">package service; //接口
public interface ISomeService { //待实现的方法
public void doFirst(); public void doSecond();
}</pre>

[
复制代码

](javascript:void(0); "复制代码")

2.SomeServiceImpl.java

image

View Code

3.MyMethodBeforeAdvice.java

image

[
复制代码

](javascript:void(0); "复制代码")

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">package aop; //前置增强
import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; public class MyMethodBeforeAdvice implements MethodBeforeAdvice{

@Override public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("目标方法执行之前执行");
}

}</pre>

[
复制代码

](javascript:void(0); "复制代码")

4.applicationContext.xml(Spring配置文件)

image

[
复制代码

](javascript:void(0); "复制代码")

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;"><?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="someService" class="service.SomeServiceImpl"></bean>

<!-- 切面:通知 -->
<bean id="beforeAdvice" class="aop.MyMethodBeforeAdvice"></bean>

<!-- *********************************************** -->

<!-- 1.*:NameMatchMethodPointcutAdvisor 名称匹配方法切入点顾问 -->
<!-- 切面:顾问 顾问(Advisor)要包装通知(Advice) -->    
<bean id="beforeAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> 
    <property name="advice" ref="beforeAdvice"></property> 
    <!--指定需要增强的方法:这里是doFirst()方法,而doSecond()方法则不会增强 -->
    <property name="mappedName" value="doFirst"></property>
    <!-- 也可以使用mappedNames指定多个方法
    <property name="mappedNames" value="doFirst,doSecond"></property> -->
</bean>

<!-- *********************************************** -->

<!-- 2.*:RegexpMethodPointcutAdvisor 正则表达式匹配方法切入点顾问 -->
<!-- 切面: 顾问 顾问(Advisor)要包装通知(Advice) -->
<!-- <bean id="beforeAdvisor"
    class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    <property name="advice" ref="beforeAdvice"></property>
    <property name="pattern" value=".*doF.*t"></property>
</bean> -->

<!-- *********************************************** -->

<!-- 代理工厂Bean -->
<bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target" ref="someService"></property>
    <property name="interceptorNames" value="beforeAdvisor"></property>
</bean>

</beans></pre>

[
复制代码

](javascript:void(0); "复制代码")

5.MyTest.java

image

[
复制代码

](javascript:void(0); "复制代码")

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">package test; //对顾问(Advisor)测试
import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import service.ISomeService; public class MyTest {
@Test public void testOne(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
ISomeService service = (ISomeService)ctx.getBean("serviceProxy");
service.doFirst();
service.doSecond();
}
}</pre>

[

复制代码
](javascript:void(0); "复制代码")
Spring中的通知(Advice)和顾问(Advisor)

在Spring中,目前我学习了几种增强的方式,和大家分享一下

之前的话:

1.AOP (Aspect Oriented Programming 面向切面编程)

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

面向对象编程是从【静态角度】考虑程序的结构,而面向切面编程是从【动态角度】考虑程序运行过程。
AOP底层,就是采用【动态代理】模式实现的。采用了两种代理:JDK动态代理和CGLIB动态代理。

基本术语(一些名词):
(1)切面(Aspect)
切面泛指[交叉业务逻辑]。事务处理和日志处理可以理解为切面。常用的切面有通知(Advice)与顾问(Advisor)。实际就是对主业务逻辑的一种增强。

(2)织入(Weaving)
织入是指将切面代码插入到目标对象的过程。代理的invoke方法完成的工作,可以称为织入。

(3) 连接点(JoinPoint)
连接点是指可以被切面织入的方法。通常业务接口的方法均为连接点

(4)切入点(PointCut)
切入点指切面具体织入的方法
注意:被标记为final的方法是不能作为连接点与切入点的。因为最终的是不能被修改的,不能被增强的。

(5)目标对象(Target)
目标对象指将要被增强的对象。即包含主业务逻辑的类的对象。

(6)通知(Advice)
通知是切面的一种实现,可以完成简单的织入功能。通知定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是执行之后执行等。切入点定义切入的位置,通知定义切入的时间。

(7)顾问(Advisor)
顾问是切面的另一种实现,能够将通知以更为复杂的方式织入到目标对象中,是将通知包装为更复杂切面的装配器。

AOP是一种思想,而非实现
AOP是基于OOP,而又远远高于OOP,主要是将主要核心业务和交叉业务分离,交叉业务就是切面。例如,记录日志和开启事务。

一:前置增强和后置增强

image

源码介绍:

1.User.java

image

View Code

2.IDao.java

image

View Code

3.UserDao.java

image

View Code

4.IUserBiz.java

image

View Code

5.UserBiz.java

image

View Code

6.LoggerAfter.java(后置增强)

image

View Code

7.LoggerBefore.java(前置增强)

image

View Code

8.applicationContext.xml(Spring配置文件)

image

View Code

当然,针对AOP的配置也可以使用代理对象 ProxyFactoryBean 代理工厂bean来实现,在测试类中:IUserBiz biz=(IUserBiz)ctx.getBean("serviceProxy");

image

View Code

9.MyTest.java

image

View Code

10.log4j.properties(日志的配置文件)

image

View Code

当然,别忘了引入我们需要的jar包啊!

常用的jar:

image

二:异常抛出增强和环绕增强

image

源码介绍:

1.User.java

image

View Code

2.UserService.java

image

View Code

3.ErrorLog.java(异常抛出增强)

image

View Code

4.AroundLog(环绕增强)

image

View Code

5.applicationContext.xml(Spring配置文件)

image

View Code

6.MyTest.java

image

View Code

三:注解增强方式实现前置增强和后置增强

image

源码介绍:

1.UserService.java

image

View Code

2.AnnotationAdvice.java(注解增强)

image

View Code

注:

java.lang.Object[] getArgs():获取连接点方法运行时的入参列表
Signature getSignature() :获取连接点的方法签名对象
java.lang.Object getTarget() :获取连接点所在的目标对象
java.lang.Object getThis() :获取代理对象本身

3.applicationContext.xml(Spring配置文件)

image

View Code

4.MyTest.java

image

View Code

四: 顾问(Advisor)实现前置增强

通知Advice是Spring提供的一种切面(Aspect)。但其功能过于简单,只能
将切面织入到目标类的所有目标方法中,无法完成将切面织入到指定目标方法中。

顾问Advisor是Spring提供的另一种切面。其可以完成更为复杂的切面织入功能。PointcutAdvisor是顾问的一种,可以指定具体
的切入点。顾问将通知进行了包装,会根据不同的通知类型,在不同的时间点,将切面织入到不同的切入点。
PointcutAdvisor接口有两个较为常用的实现类:
:NameMatchMethodPointcutAdvisor 名称匹配方法切入点顾问
:RegexpMethodPointcutAdvisor 正则表达式匹配方法切入点顾问
<property name="pattern" value=".
do.
"></property> 表示方法全名(包名,接口名,方法名)
运算符 名称 意义
. 点号 表示任意单个字符

  • 加号 表示前一个字符出现一次或者多次
  • 星号 表示前一个字符出现0次或者多次
    =====默认Advisor自动代理生成器
    DefaultAdvisorAutoProxyCreator
    =====BeanName自动代理生成器
    BeanNameAutoProxyCreator

实例:

image

源码介绍:

1.ISomeService.java

image

[
复制代码

](javascript:void(0); "复制代码")

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">package service; //接口
public interface ISomeService { //待实现的方法
public void doFirst(); public void doSecond();
}</pre>

[
复制代码

](javascript:void(0); "复制代码")

2.SomeServiceImpl.java

image

View Code

3.MyMethodBeforeAdvice.java

image

[
复制代码

](javascript:void(0); "复制代码")

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">package aop; //前置增强
import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; public class MyMethodBeforeAdvice implements MethodBeforeAdvice{

@Override public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("目标方法执行之前执行");
}

}</pre>

[
复制代码

](javascript:void(0); "复制代码")

4.applicationContext.xml(Spring配置文件)

image

[
复制代码

](javascript:void(0); "复制代码")

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;"><?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="someService" class="service.SomeServiceImpl"></bean>

<!-- 切面:通知 -->
<bean id="beforeAdvice" class="aop.MyMethodBeforeAdvice"></bean>

<!-- *********************************************** -->

<!-- 1.*:NameMatchMethodPointcutAdvisor 名称匹配方法切入点顾问 -->
<!-- 切面:顾问 顾问(Advisor)要包装通知(Advice) -->    
<bean id="beforeAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> 
    <property name="advice" ref="beforeAdvice"></property> 
    <!--指定需要增强的方法:这里是doFirst()方法,而doSecond()方法则不会增强 -->
    <property name="mappedName" value="doFirst"></property>
    <!-- 也可以使用mappedNames指定多个方法
    <property name="mappedNames" value="doFirst,doSecond"></property> -->
</bean>

<!-- *********************************************** -->

<!-- 2.*:RegexpMethodPointcutAdvisor 正则表达式匹配方法切入点顾问 -->
<!-- 切面: 顾问 顾问(Advisor)要包装通知(Advice) -->
<!-- <bean id="beforeAdvisor"
    class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    <property name="advice" ref="beforeAdvice"></property>
    <property name="pattern" value=".*doF.*t"></property>
</bean> -->

<!-- *********************************************** -->

<!-- 代理工厂Bean -->
<bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target" ref="someService"></property>
    <property name="interceptorNames" value="beforeAdvisor"></property>
</bean>

</beans></pre>

[
复制代码

](javascript:void(0); "复制代码")

5.MyTest.java

image

[
复制代码

](javascript:void(0); "复制代码")

<pre style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">package test; //对顾问(Advisor)测试
import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import service.ISomeService; public class MyTest {
@Test public void testOne(){
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
ISomeService service = (ISomeService)ctx.getBean("serviceProxy");
service.doFirst();
service.doSecond();
}
}</pre>

[
复制代码

](javascript:void(0); "复制代码")

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容