AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
通知:advice, 通知定义了切面是什么以及合适使用。
通知的5种类型:
1、Before——在方法被调用之前调用通知;
2、After——在方法完成后调用通知,无论方法是否执行成功;
3、After-returning——在方法成功执行之后通知;
4、After-throwing——在方法抛出异常之后通知;
5、Around——通知包裹了被通知的方法,在被通知的方法调用的前后执行自定义的行为;
切点:pointcut :定义何处进行通知;
切面:aspect:通知和切点的结合;
execution(* com.springinaction.springidol.Instrument.play(..) && within(com.springinaction.springidol.*))
解释:
execution:方法执行时触发
* :返回任意类型
com.springinaction.springidol.Instrument:类
play:切面方法
.. : 使用任意参数
&&:and操作符
within(com.springinaction.springidol.*):当com.springinaction.springidol包下任意方法被调用时
下面是一个通知例子:
public class Audience{
public void takeSeats(){ //表演前
System.out.println("the audience is taking their seats...");
}
public void turnOffCellPhones(){//表演前
System.out.println("the audience is turning off their CellPhones");
}
public void applaud(){//表演后
System.out.println("鼓掌.....");
}
public void demandRefund(){//失败后
System.out.println("boo! we want our money back!");
}
}
声明前置、后置通知: (这个切面是由切点和通知组成)
<aop:config>
<aop:aspect ref="audience"><!--引用audience bean-->
<aop:before pointcut="execution (* com.springinaction.springidol.Performer.perform(..))"
method="takeSeats" /><!--表演前-->
<aop:before pointcut="execution (* com.springinaction.springidol.Performer.perform(..))"
method="turnOffCellPhones" /><!--表演前-->
<aop:after-returning pointcut="execution (* com.springinaction.springidol.Performer.perform(..))"
method="applaud" /><!--表演后-->
<aop:after-throwing pointcut="execution (* com.springinaction.springidol.Performer.perform(..))"
method="demandRefund" /><!--表演失败后-->
</aop:aspect>
</aop:config>
以上的写法,可以把pointcut="execution (* com.springinaction.springidol.Performer.perform(..))"单拿出来,
然后用poingcut-ref引用id;
声明环绕通知;
public void watchPerformance(ProceedingJoinPoint joinpoint){
try{
long start = System.currentTimeMillis();
joinpoint.proceed();//执行被通知的方法——perform
long end = System.currentTimeMillis();
}catch{
System.out.println("Boo,we want our money back!");
}
}
<aop:config>
<aop:aspect ref="audience">
<aop:pointcut id="performance2" expression="execution (* com.springinaction.springidol.Performer.perform(..))" />
<!-- 这个method会把切点的方法通过joinpoint参数传递进去 -->
<aop:around pointcut-ref="performance2" method="watchPerformance()" />
</aop:aspect>
</aop:config>
为通知传递参数:
<aop:config>
<aop:aspect ref="magician">
<!-- 配置切点,并指定切点的类型为String 和参数是thoughts -->
<aop:pointcut id="thinking"
expression="execution(* com.springinaction.springidol.Thinker.thinkOfSomething(String)) and args(thoughts) " />
<!-- 在执行thinkOfSomething之前,把参数传递给interceptThoughts方法,并指明参数名称 -->
<aop:before pointcut-ref="thinking" method="interceptThoughts" arg-names="thoughts" />
</aop:aspect>
</aop:config>
通过切面引入新的功能:
<aop:aspect>
<aop:declare-parents
type-matching="com.springinaction.springidol.Performer+" <!-- 切面 -->
implement-interface="com.springinaction.springidol.Contestant" <!-- 接口 -->
default-impl="com.springinaction.springidol.GraciousContestant" /> <!-- Contestant的实现 -->
</aop:aspect>
Performer被转化成Contestant类型,GraciousContestant为新加入的功能