IOC和AOP是Spring的兩大基石,AOP(面向方面編程),也可稱爲面向切面編程,是一種編程範式,提供從另外一個角度來考慮程序結構從而完善面向對象編程(OOP)。java
在進行 OOP 開發時,都是基於對組件(好比類)進行開發,而後對組件進行組合,OOP 最大問題就是沒法解耦組件進行開發,好比咱們上邊舉例,而 AOP 就是爲了克服這個問題而出現的,它來進行這種耦合的分離。AOP 爲開發者提供一種進行橫切關注點(好比日誌關注點)分離並織入的機制,把橫切關注點分離,而後經過某種技術織入到系統中,從而無耦合的完成了咱們的功能。正則表達式
在 AOP 中,經過切入點選擇目標對象的鏈接點,而後在目標對象的相應鏈接點處織入通知,而切入點和通知就是切面(橫切關注點),而在目標對象鏈接點處應用切面的實現方式是經過 AOP 代理對象,如圖所示。spring
AOP代理就是 AOP框架經過代理模式建立的對象,Spring使用 JDK動態代理或 CGLIB代理來實現, Spring 缺省使用 JDK 動態代理來實現,從而任何接口均可被代理,若是被代理的對象實現不是接口將默認使用 CGLIB 代理,不過 CGLIB 代理固然也可應用到接口。AOP 代理的目的就是將切面織入到目標對象。express
新建工程,導入Spring中對應的包,最後引入的jar包以下所示(有些包spring的lib下沒有,須要另外下載):編程
(1)定義目標接口框架
package com.log; public interface IHelloWorldService { public void sayHello(); }
(2)定義目標接口實現類ide
package com.log; public class HelloWorldService implements IHelloWorldService { @Override public void sayHello() { System.out.println("---hello world---"); } }
(3)定義切面支持類模塊化
package com.log; public class HelloWorldAspect { public void beforeAdvice() { System.out.println("---before advice---"); } public void afterAdvice() { System.out.println("---after advice---"); } }
(4)在XML中進行配置測試
<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-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> <!-- 配置目標類 --> <bean id="helloWorldService" class="com.log.HelloWorldService"/> <!-- 配置切面 --> <bean id="aspect" class="com.log.HelloWorldAspect"/> <aop:config> <aop:pointcut id="pointcut" expression="execution(* com.log..*.*(..))"/> <!-- aop:aspect的ref引用切面支持類的方法 --> <aop:aspect ref="aspect"> <aop:before pointcut-ref="pointcut" method="beforeAdvice"/> <aop:after pointcut-ref="pointcut" method="afterAdvice"/> </aop:aspect> </aop:config> </beans>
切入點使用<aop:config>標籤下的<aop:pointcut>配置, expression屬性用於定義切入點模式,默認是AspectJ語法,「 execution(* cn.javass..*.*(..))」表示匹配cn.javass包及子包下的任何方法執行。關於expression屬性如何配置請點擊:expression配置spa
切面使用<aop:config>標籤下的<aop:aspect>標籤配置,其中「 ref」用來引用切面支持類的方法。
前置通知使用<aop:aspect>標籤下的<aop:before>標籤來定義, pointcut-ref屬性用於引用切入點Bean, 而method用來引用切面通知實現類中的方法,該方法就是通知實現,即在目標類方法執行以前調用的方法。
最終通知使用<aop:aspect>標籤下的<aop:after >標籤來定義,切入點除了使用pointcut-ref屬性來引用已經存在的切入點,也能夠使用pointcut屬性來定義,如pointcut="execution(* cn.javass..*.*(..))", method屬性一樣是指定通知實現,即在目標類方法執行以後調用的方法。
(5)測試運行
package com.log; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AopTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("aopBean.xml"); IHelloWorldService hello = context.getBean("helloWorldService", IHelloWorldService.class); hello.sayHello(); HelloWorldAspect advice = context.getBean("aspect", HelloWorldAspect.class); advice.beforeAdvice(); } }
(6)輸出結果