什么是AOP
。AOP:Aspect Oriented Programming 的缩写,意思为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术
在运行时,动态的将代码切入到类的指定方法,指定位置上的编程思想就是面向切面编程。
。主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等。
AOP的实现方式
。预编译
- AspectJ
。运行期动态代理(JDK动态代理、CGLib动态代理)
- SpringAOP、JboosAOP
AOP的相关概念
切面(Aspect) | 一个关注点的模块化,这个关注点可能会横切多个对象 |
连接点(Joinpoint) | 程序执行过程中的某个特定的点 |
通知(Advice) | 在切面的某个特定的连接点上执行的动作 |
切入点(Pointcut) | 匹配连接点的断言,在AOP中通知和一个切入点表达式关联 |
引入(Introduction) | 在不修改类代码的前提下,为类添加新的方法和属性 |
目标对象(Target Object) | 被一个或者多个切面所通知的对象 |
AOP代理(AOP Proxy) | AOP框架创建的对象,用来实现切面契约(aspect contract)(包括通知方法执行等功能) |
织入(Weaving) | 把切面连接到其他的应用程序类型或者对象上,并创建一个被通知对象,分为:编译时织入、类加载时织入、执行时织入。 |
Spring框架中AOP的用途
。提供了声明式的企业服务,特别是EJB的替代服务的声明
。允许用户定制自己的方面,已完成OOP(面向对象)与AOP的互补使用
Schema — based AOP
基于配置的AOP实现
Spring所有的切面和通知其都必须放在一个<aop:config>内,(可以配置包含多个<aop:config>元素),每一个<aop:config>可以包含pointcut,advisor和aspect元素(它们必须按照这个顺序进行声明)
<aop:config>风格的配置大量使用了Spring的自动代理机制
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
...
</aop:aspect>
</aop:config>
<bean id="aBean" class="..."></bean>
advice(前置通知):
<bean id="moocAspect" class=com.imooc.aop.advice.MoocAspect"></bean>
<aop:config>
<!-- 对应的通知在moocAspect类中实现-->
<aop:aspect id="moocAspectAOP" ref="moocAspect">
<!-- 这个biz包下面所有以Biz结尾的所有的类的所有方法-->
<aop:pointcut expression="execution(* com.imooc.aop.advice.biz.*Biz.*(..))" id="moocPointcut"/>
<!-- 所有以Biz结尾的所有的类的方法在执行之前执行 "before"方法-->
<aop:before method="before" pointcut-ref="moocPointcut"/>
<!-- 返回之后的通知-->
<aop:after-returning method="afterReturning" pointcut-ref="moocPointcut"/>
<!-- 报错之后的通知-->
<aop:after-throwing method="afterThrowing" pointcut-ref="moocPointcut"/>
<!-- 相当于finally,程序结束之前执行-->
<aop:after method="after" pointcut-ref="moocPointcut"/>
</aop:aspect>
</aop:config>
Around advice(循环通知、环绕通知)
通知方法的第一个参数必须是ProceedingJoinPoint类型
<bean id="moocAspect" class=com.imooc.aop.advice.MoocAspect"></bean>
<aop:config>
<!-- 对应的通知在moocAspect类中实现-->
<aop:aspect id="moocAspectAOP" ref="moocAspect">
<!-- 这个biz包下面所有以Biz结尾的所有的类的所有方法-->
<aop:pointcut expression="execution(* com.imooc.aop.advice.biz.*Biz.*(..))" id="moocPointcut"/>
<!-- 所有以Biz结尾的所有的类的方法在执行之前执行 "before"方法-->
<aop:before method="before" pointcut-ref="moocPointcut"/>
<aop:after method="after" pointcut-ref="moocPointcut"/>
<!-- 执行AspectBiz类中的init方法它的参数类型必须是String和int,参数名必须为bizName和times-->
<aop:around method="aroundInit" pointcut="execution(* com.imooc.aop.advice.biz.AspectBiz.init(String,int))
and args(bizName,times)"/>
</aop:aspect>
</aop:config>
moocAspect类
public Object aroundInit(ProceedingJoinPoint pjp,String bizName,int times){
System.out.pringln(bizName+" " + times);
Object obj = null;
try{
System.out.pringln("MoocAspect aroundInit 1.");
obj = pjp.proceed();
System.out.pringln("MoocAspect aroundInit 2.");
}catch(Throwable e){
e.printStackTrace();
}
return obj;
}