Aop(aspect object programming)面向切面編程
功能: 讓關注點代碼與業務代碼分離!spring
關注點express
重複代碼就叫作關注點;編程
切面spa
關注點造成的類,就叫切面(類)!代理
面向切面編程,就是指對不少功能都有的重複的代碼抽取,再在運行的時候往業務方法上動態植入「切面類代碼」。code
切入點xml
執行目標對象方法,動態植入切面代碼。對象
能夠經過切入點表達式,指定攔截哪些類的哪些方法; 給指定的類在運行的時候植入切面類代碼。blog
Aop實現的原理就是代理。接口
1) 先引入aop相關jar文件 (aspectj aop優秀組件)
spring-aop-3.2.5.RELEASE.jar 【spring3.2源碼】
aopalliance.jar 【spring2.5源碼/lib/aopalliance】
aspectjweaver.jar 【spring2.5源碼/lib/aspectj】或【aspectj-1.8.2\lib】
aspectjrt.jar 【spring2.5源碼/lib/aspectj】或【aspectj-1.8.2\lib】
注意: 用到spring2.5版本的jar文件,若是用jdk1.7可能會有問題。
須要升級aspectj組件,即便用aspectj-1.8.2版本中提供jar文件提供。
2)bean.xml中引入aop名稱空間
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="userDao" class="com.juaner.spring.aop.UserDao" /> <bean id="orderDao" class="com.juaner.spring.aop.OrderDao"/> <bean id="aop" class="com.juaner.spring.aop.Aop"/> </beans>
開啓aop註解
<!--開啓aop註解--> <aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>
使用註解
@Aspect 指定一個類爲切面類
@Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))") 指定切入點表達式
@Before("pointCut_()") 前置通知: 目標方法以前執行
@After("pointCut_()") 後置通知:目標方法以後執行(始終執行)
@AfterReturning("pointCut_()") 返回後通知: 執行方法結束前執行(異常不執行)
@AfterThrowing("pointCut_()") 異常通知: 出現異常時候執行
@Around("pointCut_()") 環繞通知: 環繞目標方法執行
@Aspect //指定爲切面類
public class Aop { //指定切入點表達式,攔截哪些方法,即爲哪些類生成代理對象 @Pointcut("execution(* com.juaner.spring.aop.*.*(..))") public void testPt_(){ } @Before("testPt_()") public void begin(){ System.out.println("事務開始!"); } @After("testPt_()") public void commite(){ System.out.println("事務提交!"); } @AfterReturning("testPt_()")//出現異常不執行 public void afterReturning(){ System.out.println("調用目標方法結束!"); } @AfterThrowing("testPt_()")//出現異常才執行 public void afterThrowing(){ System.out.println("目標方法出現異常!"); } @Around("testPt_()") public void around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("環繞前"); Object proceed = pjp.proceed();//執行目標方法 System.out.println("環繞後"); } }
使用切面類
IUserDao userDao = (IUserDao) ac.getBean("userDao"); userDao.save();
若是userDao實現了接口,則userDao爲動態代理對象
不然userDao爲cglib代理對象
配置切入點
<?xml version="1.0" encoding="UTF-8"?> <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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="userDao" class="com.juaner.spring.xmlaop.UserDao"></bean> <bean id="orderDao" class="com.juaner.spring.xmlaop.OrderDao"/> <bean id="aop" class="com.juaner.spring.xmlaop.Aop"></bean> <!--aop配置--> <aop:config> <!--定義一個切入點表達式,攔截哪些方法--> <aop:pointcut id="pt" expression="!execution(* com.juaner.spring.xmlaop.OrderDao.*(..))"/> <!--切面--> <aop:aspect ref="aop"> <aop:before method="begin" pointcut-ref="pt"/> <aop:after method="commite" pointcut-ref="pt"/> <aop:after-returning method="afterReturning" pointcut-ref="pt"/> <aop:after-throwing method="afterThrowing" pointcut-ref="pt"/> <aop:around method="around" pointcut-ref="pt"/> </aop:aspect> </aop:config> </beans>
切入點表達式語法定義以下:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- dao 實例 --> <bean id="userDao" class="cn.itcast.g_pointcut.UserDao"></bean> <bean id="orderDao" class="cn.itcast.g_pointcut.OrderDao"></bean> <!-- 切面類 --> <bean id="aop" class="cn.itcast.g_pointcut.Aop"></bean> <!-- Aop配置 --> <aop:config> <!-- 定義一個切入點表達式: 攔截哪些方法 --> <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.*.*(..))" id="pt"/>--> <!-- 【攔截全部public方法】 --> <!--<aop:pointcut expression="execution(public * *(..))" id="pt"/>--> <!-- 【攔截全部save開頭的方法 】 --> <!--<aop:pointcut expression="execution(* save*(..))" id="pt"/>--> <!-- 【攔截指定類的指定方法, 攔截時候必定要定位到方法】 --> <!--<aop:pointcut expression="execution(public * cn.itcast.g_pointcut.OrderDao.save(..))" id="pt"/>--> <!-- 【攔截指定類的全部方法】 --> <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.*(..))" id="pt"/>--> <!-- 【攔截指定包,以及其自包下全部類的全部方法】 --> <!--<aop:pointcut expression="execution(* cn..*.*(..))" id="pt"/>--> <!-- 【多個表達式】 --> <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) || execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--> <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) or execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--> <!-- 下面2個且關係的,沒有意義 --> <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) && execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--> <!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) and execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--> <!-- 【取非值】 --> <!--<aop:pointcut expression="!execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--> <aop:pointcut expression=" not execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/> <!-- 切面 --> <aop:aspect ref="aop"> <!-- 環繞通知 --> <aop:around method="around" pointcut-ref="pt"/> </aop:aspect> </aop:config> </beans>