1.什么是AOP
AOP(Aspect Oriented Programming) 即面向切面编程,是设计模式的延续。设计模式追求的是调用者和被调用者之间的解耦。 AOP 可以说是对此目标的一种实现。
AOP 的核心思想: 将应用程序中的商业逻辑和对其提供支持的通用服务进行分离。
AOP 相关术语
>> 连接点(Joinpoint)
程序执行的某个特定的位置: 如类的开始,结束 ,某个方法调用前和调用后。方法抛出异常后。
连接点由两个信息确定:第一是用方法表示的程序执行点,第二是用相对点表示的方位。
>> 切点 (Pointcut)
个人理解就是: 多个连接点的集合,一个切点对应多个连接点。
>> 增强(Advice)
增强是织入到目标连接点上的一段代码。 结合切点一起使用才能确定特定的连接点并实施增强逻辑
>> 织入 (Weaving)
织入是将增强添加对目标类具体连接点上的过程。
分三层织入:
1. 编译起期织入。
2. 类装载期织入。
3. 动态代理织入。
>> 代理 (Proxy)
一个类被AOP织入增强后,就产生了一个结果类,代理类即可能是和原类具有相同接口的类,
所以我们可以采用调用原类的方式调用代理类。
>> 切面(Aspect)
切面由切点和增强(引介)组成。既包括横切逻辑的定义,也包括连接点的定义。
Spring 支持5种类型的增强:
1 . 前置增强:org.springframework.aop.BeforeAdvice 代表前置增强,因为Spring 只支持方法级的增强,所以MethodBeforeAdvice 是目前可用的前置增强。
前置增强实现的接口 : MethodBeforeAdive
2 . 后置增强:org.springframework.aopAfterReturningAdvice 代表后置增强。表示在目标方法执行后实施增强。
后置增强实现的接口:AfterReturningAdvice
3 . 环绕增强:org.aopalliance.intercept.MethodInterceptor 代表环绕增强,表示在目标方法执行前后实施增强。
环绕增强实现的接口: MethodInterceptor 会有一个invoke方法 ,在这个方法中有一个参数。MethodInvocation 类,在MethodInvocation 中
取到 一个peoceed的函数 进行分割 前后!
4 . 异常抛出增强 : org.springframework.aop.ThrowsAdvice 代表抛出异常增强。表示在目标方法抛出异常后实施增强。
异常抛出增强实现一个:ThrowsAdvice 这个接口中没有定义任何方法 需要 自己写一个 afterThrowing 方法 系统会自动的识别!
5 . 引介增强: org.springframework.aop.IntroductionInterceptor 代表引介增强。表示在目标类中添加一些新的方法和属性。
在增强上面我们会发现还有一个问题,增强被织入到目标类的所有方法中,如果我们只是想在某些方法应用增强呢?
这个就要用到 静态普通方法名匹配切面
StaticMethodMatcherPointcutAdvisor 代表一个静态方法匹配切面,它通过StaticMethodMatcherPointcut 定义切点。通过类过滤和方法名匹配定义切点。
总共两种方式:
第一种实例:
<!-- 静态增强方法 -->
<bean id="greetingBefore" class="dream.advice.GreetingBeforeAdvice"></bean>
<!-- 静态匹配切面-->
<bean id="greetingAdvistor" class="dream.advice.GreetingAdvisor">
<!--需要在切面中注入增强方法-->
<property name="advice" ref="greetingBefore"></property>
</bean>
<!-- 静态匹配目标 -->
<bean id="waiterStatic" class="dream.biz.imple.Waiter"></bean>
<bean id="seller" class="dream.biz.imple.Seller"></bean>
<!-- 静态普通匹配切面代理 -->
<bean id="parent" abstract="true" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interceptorNames">
<list>
<value>greetingAdvistor</value>
</list>
</property>
<property name="proxyTargetClass" value="true"></property>
</bean>
<!-- waiter代理 -->
<bean id="waiter1" parent="parent">
<property name="target" ref="waiterStatic"></property>
</bean>
<!-- seller代理 -->
<bean id="seller1" parent="parent">
<property name="target" ref="seller"></property>
</bean>
第二种实例:无需使用顾问
<!--增强方法 -->
<bean id="greetingBefore" class="dream.advice.GreetingBeforeAdvice"></bean>
<!-- 静态匹配目标 -->
<bean id="waiterStatic" class="dream.biz.imple.Waiter"></bean>
<bean id="seller" class="dream.biz.imple.Seller"></bean>
<!-- 静态正则表达式方法匹配切面 -->
<bean id="regexpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="patterns">
<list>
<value>.*greetTo.*</value>
</list>
</property>
<property name="advice" ref="greetingBefore"></property>
</bean>
<bean id="Reg" abstract="true" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 拦截 -->
<property name="interceptorNames">
<list>
<value>regexpAdvisor</value>
</list>
</property>
<property name="proxyTargetClass" value="true"></property>
</bean>
<bean id="waiterReg" parent="Reg">
<property name="target" ref="waiterStatic"></property>
</bean>
<bean id="SellerReg" parent="Reg">
<property name="target" ref="seller"></property>
</bean>