我们来分析一下上节课的application.xml里面代码的写法,注意上节课的切点表达式抽取跟这节课关系不大,所以我们分析的是没抽取的代码
原写法:
x
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--配置目标对象,我们会在src/test/java/com.huanf.test/AopTest类里面进行测试target-->
<bean id="target" class="com.huanf.aop.Target"></bean>
<!--配置切面对象-->
<bean id="myAspecT" class="com.huanf.aop.MyAspect"></bean>
<!--配置织入,内部要配置: 哪些方法(其实指的就是切点)需要进行哪些增强(其实指定就是前置增强、后置增强、其它增强)-->
<aop:config>
<!--声明切面,即指定上面的id作为切面,不然上面我们写的id="myAspecT"只是一个普通的bean,当声明了之后myAspecT就不再是普通的bean,而是切面-->
<aop:aspect ref="myAspecT">
<!--切面=切点+通知,通知也称为增强。before表示前置增强,method表示哪个方法(在MyAspect类里面的哪个方法)要进行前置增强。
pointcut表示切点,execution里面表示对Target类的save方法增强。下面那行的execution括号里面的叫'切点表达式'-->
<aop:before method="before_met" pointcut="execution(* com.huanf.aop.*.*(..))"/>
<!--上面那行的意思: 当访问save方法时,save方法会进行前置增强,前置增强的代码在MyAspect类的before_met方法里面-->
</aop:aspect>
</aop:config>
<!--把上面那个<aop:config>标签注释掉,那么我们在com.huanf.test.AopTest类里面测试的就是未增强的save方法-->
<!--如果要增强别的方法的话,就把execution括号里面的全限定名改掉即可-->
</beans>
首先分析aop:config标签里面的写法:
1、aop:config: aop的配置
2、<aop:aspect ref="xxx">: 声明切面,ref指定某个类里面的切面
3、<aop:kkk method="xxx" pointcut="execution(yyy)"/>:kkk表示增强种类是前置增强还是后置增强,yyy方法(切点方法)+xxx方法(增强方法)=切面,pointcut里面的是切点表达式(通过一个表达式可以指定多个切点方法)。这节课主要讲before位置的参数,接下来会着重学习 '通知(也叫增强)的种类'
通知的配置语法,下面讲的目标方法指的是切点表达式里面的方法,例如save方法,该方法也叫切点方法:
<aop:通知类型 method="切面类中的方法名" pointcut="切点表达式"></aop:通知类型>
名称 | 标签 | 说明 |
---|---|---|
前置通知 | < aop:before > | 在目标方法之前执行 |
后置通知 | < aop:after-returning > | 在目标方法之后执行 |
环绕通知 | < aop:around > | 在目标方法之前和之后都执行 |
异常抛出通知 | < aop:after-throwing > | 当目标方法出现异常后执行 |
最终通知 | < aop:after > | 无论目标方法执行是否有异常都会执行 |
上面的'通知'也叫'增强',我们通常写的时候写'通知',读的时候读'增强'
具体操作:
第一步: 把MyAspect类修改为如下
public class MyAspect {
public void before_met(){System.out.println("前置增强 -- xml方式实现aop");}
public void afterReturning_met(){System.out.println("后置增强 -- xml方式实现aop");}
}
第二步: 在applicationContext.xml里面的'<aop:before method="before_met" pointcut="execution(* com.huanf.aop..(..))"/>'的下一行添加如下
<aop:after-returning method="afterReturning_met" pointcut="execution(* com.huanf.aop.*.*(..))"/>
第三步: 在AopTest类里面运行,即可测试前置增强和后置增强
第四步: 把MyAspect类修改为如下
public class MyAspect {
public void before_met(){
System.out.println("前置增强 -- xml方式实现aop");
}
public void afterReturning_met(){System.out.println("后置增强 -- xml方式实现aop");}
public Object around_met(ProceedingJoinPoint pjp) throws Throwable {//ProceedingJoinPoint表示正在执行的连接点,也就是切点,目的是为了下面能执行切点方法
System.out.println("环绕前增强 -- xml方式实现aop");
Object proceed = pjp.proceed();//目标方法(也叫切点方法)
System.out.println("环绕后增强 -- xml方式实现aop");
return proceed;
}
}
第五步: 在applicationContext.xml里面,把上面第2步的配置注释了,然后添加如下,原因:'前置增强后置增强'和'环绕增强'能实现相同的效果,所以以示区分 即注释aop:aspect标签里面的aop:before、aop:after-returning 添加如下
<aop:around method="around_met" pointcut="execution(* com.huanf.aop.*.*(..))"/>
第六步: 在AopTest类里面运行,即可测试环绕增强
第七步: 把MyAspect类修改为如下
public class MyAspect {
public void before_met(){
System.out.println("前置增强 -- xml方式实现aop");
}
public void afterReturning_met(){System.out.println("后置增强 -- xml方式实现aop");}
public Object around_met(ProceedingJoinPoint pjp) throws Throwable {//ProceedingJoinPoint表示正在执行的连接点,也就是切点,目的是为了下面能执行切点方法
System.out.println("环绕前增强 -- xml方式实现aop");
Object proceed = pjp.proceed();//目标方法(也叫切点方法)
System.out.println("环绕后增强 -- xml方式实现aop");
return proceed;
}
public void afterThrowing_met(){
System.out.println("异常抛出后增强 -- xml方式实现aop");
}
}
第八步: 把Target类修改为如下
public class Target implements TargetInterface {
public void save() {
int i = 1/0;//制造异常。注意,这行如果在下面那个save的上面,那么下面那行是不会被执行的,如果把这行放到save方法的下一行,那save方法就会被执行
System.out.println("save方法正在启动 -- xml方式实现aop");
}}
第九步: 在applicationContext.xml里面添加如下
<aop:after-throwing method="afterThrowing_met" pointcut="execution(* com.huanf.aop.*.*(..))"/>
第十步: 在AopTest类里面运行,即可测试异常抛出后增强。运行后会在控制台输出: 异常抛出后增强 -- xml方式实现aop、/ by zero报错
第十一步: 在MyAspect类里面添加如下
public void after_met(){
System.out.println("最终增强 -- xml方式实现aop");
}
第十二步: 在applicationContext.xml里面添加如下
<aop:after method="after_met" pointcut="execution(* com.huanf.aop.*.*(..))"/>
第十三步: 在AopTest类里面运行,即可测试异常抛出后增强。运行后会在控制台输出: 最终增强 -- xml方式实现aop、/ by zero报错
第十四步: 为了方便,我把Target类修改为如下
public class Target implements TargetInterface {
public void save() {
//为了方便我把下一行注释了,如果要演示'异常抛出后增强',那么就把下一行解开注释。
//int i = 1/0;//制造异常。注意,这行如果在下面那个save的上面,那么下面那行是不会被执行的,如果把这行放到save方法的下一行,那save方法就会被执行
System.out.println("save方法正在启动 -- xml方式实现aop");
}}