@·AOP基本概念及其特点
1)什么是AOP
·AOP:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
·主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等。
2)对切面的理解
程序中的每一个模块或者说功能,任何一个模块中都要记录它的日志、事务、安全验证等等,给我们带来的工作量非常大。
当程序到达某种规模时,尤其是格式调整之类的,这种改动量是非常大的。如果通过切面方式,对开发人员是不可见的,默认地会对每一个子模块记录日志等这些工作。通过预编译或者动态代理的方式来执行这个功能,
对开发人员是透明,他不需要知道。
切面是和功能垂直的,也就是切面是横切与各个功能之上的
3)AOP实现方式
①预编译-AspectJ
②运行期动态代理(JDK动态代理、CGLib动态代理)-SpringAOP、JbossAOP
4)AOP几个相关概念
①切面---一个关注点的模块化,这个关注点可能会横切多个对象
②连接点--程序执行过程中的某个特定的点
③通知----在切面的某个特定的连接点上执行的动作
④切入点--匹配连接点的断言,在AOP中通知和一个切入点表达式关联
⑤引入----在不修改类代码的前提下,为类添加新的方法和属性
⑥目标对象-被一个或者多个切面所通知的对象
⑦AOP代理--AOP框架创建的对象,用来实现切面契约(包括通知方法执行等功能)
⑧织入---把切面连接到其他的应用程序类型或者对象上,并且创建一个被通知的对象,分为:编译时织入,执行时织入
Spring的AOP实现
·纯java实现,无需特殊的编译过程·,不需要控制类加载器层次
·目前只支持方法执行连接点(通知Spring Bean的方法执行)
·不是为了提供最完整的AOP实现(尽管它非常强大);而是侧重于提供一种AOP实现和Spring IOC容器之间的整合,用于帮助解决企业应用中的常见问题
·Spring AOP不会与AspectJ竞争,从而提供综合全面的AOP解决方案。
有接口和无接口的Spring AOP实现区别
·Spring AOP默认使用标准的JAVASE动态代理作为AOP代理,使得任何接口(或者接口集)都可以被代理
·Spring AOP中也可以使用CGLIB代理(如果一个业务对象并没有实现一个接口)
Schema--based AOP
Spring所有的切面和通知器都必须放在一个<aop:config>内(可以配置包含多个<aop:config>元素),每一个<aop:config>可以包含pointcut,advisor和aspect元素
(它们必须按照这个顺序进行声明)
配置切入点Pointcut
切入点的配置就是配置业务类中的哪些方法在执行前后会调用切面中的方法,切入点是和通知advice配合使用,配置了切入点,通知才会知道在哪些业务类的哪些方法执行
<aop:pointcut expression="execution(* com.imooc.aop.schema.advice.biz.*Biz.*(..))" id="moocPiontcut"></aop:pointcut> <br>
expression配置方式介绍:
execution用于匹配方法执行的连接点
aop:after 所指定的切面方法,会在对应类中的方法执行完后再执行。
before所指定的切面方法 会在监控的方法执行前执行;
after-returning所指定的切面方法 会在监控方法正常执行结束后执行;
after-throwing所指定的切面方法 会在监控方法抛出异常时执行;
after所指定的切面方法 会在监控方法执行结束后,无论方法执行时是否有异常抛出,均会执行此切面方法。
<aop:before method="before" pointcut-ref="moocPiontcut"></aop:before> 指的是切面MoocAspect中的方法,会在业务类中的方法执行之前被执行。 method="before"中的before就是切面MoocAspect中的方法
after finally advice 执行完finally后执行的切面方法。
after-throwing. 当抛出某个异常时,需要调用的切面方法。
After(finally) advice 在方法无论是否正常执行之后都会返回的通知。。。无论方法是否正常介绍(是否抛出异常)最后都会进入到after方法的切入点执行after方法
<aop:config>
<aop:aspect id="myAspectAOP" ref="myAspect">
<!--该表达式的意思是,切入点是 aop.schema.advice.biz.AspectBiz 类中的所有方法 -->
<aop:pointcut expression="execution(* aop.schema.advice.biz.AspectBiz.*(..))" id="myPiontcut"/>
<!--指定前置通知, method中的名称即是 myAspect中的方法名,pointcut-ref 指向某一个切入点 -->
<aop:before method="before" pointcut-ref="myPiontcut"/>
<!--指定在 切入点方法返回之后调用的通知 ,method中的名称即是 myAspect中的方法名 -->
<aop:after-returning method="afterReturning" pointcut-ref="myPiontcut"/>
<!--指定在 切入点方法抛出异常后调用的通知,抛出异常后,不会执行after-returning -->
<aop:after-throwing method="afterThrowing" pointcut-ref="myPiontcut"/>
<!--指定后置通知 当有异常抛出时 执行throwing ,但是由于是非正常结束,所以after-returning就是不会执行了,但是after 是不管你是否正常结束,都一定会执行。 -->
<aop:after method="after" pointcut-ref="myPiontcut"/>
</aop:aspect>
advice的4种类型:1.before执行切入点之前执行 2.after-returning 切入点执行后执行 3.after-throwing 执行切入点发生异常时执行 4.after 最后必须执行的一个函数,相当于finally
</aop:config>
Around advice 通知方法的第一个参数必须是Proceeding Join Point类型
环绕通知的时候,如果方法体有异常 那么抛出异常后 不再执行 环绕通知下边的代码
introductions(简介):简介允许一个切面声明一个实现指定接口的通知对象,并且提供了一个接口实现类来代表这些对象
由 <aop:aspect>中的<aop:declare-parents>元素声明该元素用于声明所匹配的类型拥有一个新的parent
说白了就是为那些匹配的类加上一个接口,并且加上实现
.schema-defined aspects只支持singleton model
@Spring AOP API:
1、这是Spring1.2历史用法,现在(V4.0)仍然支持;
2、这是SpringAOP基础,不得不了解;
3、现在的用法也是基于历史的,只是更简便了。
Pointcut
实现之一:NameMathchMethodPoincut,根据方法名进行匹配
成员变量:mappedNames,匹配的方法名集合
Before advice
1:一个简单的通知类型
2:只是在进入方法前被调用,不需要MethodInvocation对象
3:前置通知可以在连接点执行前插入自定义行为,但不能改变返回值
Throws advice
1:如果连接点异常,throws advice在连接点返回后调用
2:如果throws-advice的方法抛出异常,那么它将覆盖原有异常
3:接口org.springframework.aop.ThrowsAdvice不包含任何方法,仅仅是一个声明,实现类需要实现类似下面的方法:
void afterThroeing([Method,args,target],ThrowableSubclass)
after Returning advice
1:后置通知必须实现org.springframework.aop.AfterReturningAdvice接口
2:可以访问返回值(但不能进行修改)、被调用的方法、方法的参数和目标
3:如果抛出异常,将会拦截器链,替代返回值
Interception around advice
Spring的切入点模型使得切入点可以独立与advice重用,以针对不同的advice可以使用相同的切入点
Introduction advice
1:Spring把引入通知作为一种特殊的拦截通知
2:需要IntroductionAdvisor和IntroductionInterceptor
3:仅适用于类,不能和任何切入点一起使用
ProxyFactoryBean
.使用ProxyFactoryBean或者其他IoC相关类来创建AOP代理的最重要的好处是通知和切入点也可以由IoC来管理
.被代理的类没有任何接口,使用CGLIB代理,否则JDK代理<br>
.通过proxyTargetClass为true,可强制使用CGLIB <br>
.如果目标类实现了一个(或者多个)接口,那么创建代理的类型将依赖ProxyFactoryBean的配置
.如果ProxyFactoryBean的proxyInterfaces属性被设置为一个或者多个全限定接口名,基于JDK的代理将被创建.
未使用spring之前,需要自己管理bean。不同bean类型不同,要在这些自己创建的bean类型上面实现的类似spring中advice的功能,比较复杂。
使用了Spring之后,Spring IoC可以帮你管理bean(以前是通过硬代码的方式new一个bean等),其原理是通过ProxyFactoryBean来实现,即统一的ProxyFactoryBean能帮你管理各种各样的bean,然后在上面实现各种advice(拦截器?),并且实现这些功能这是基于配置的而不需要硬编码。ProxyFactoryBean具体是如何实现的,是通过jdk自身的动态代理或者CGLib。
AspectJ:
1、@AspectJ的风格类似纯java注解的普通java类;
2、Spring可以使用AspectJ来做切入点解析;
3、AOP的运行时仍旧是纯的SpringAOP,对AspectJ的编译器或者织入无依赖性。
1、@AspectJ切面使用@AspectJ注解配置,拥有@Aspect的任何bean将被Spring自动识别并应用。
2、用@AspectJ注解的类可以有方法和字段,他们也可能包括切入点(pointcut),通知(Advice)和引入(introduction)声明。
通知
1.@Before("表示式、连接点方法名()")
2.@AfterReturing 可以使用returing绑定返回值 Object
3.@AfterThrowing throwing同上
4.@After finally
5.@Around 第一个参数必须是ProceedingJoinPoint proceed(),proceed(Object[])