學習Spring筆記五


AOP基本概念

連接點 joinpoint,相對應一個線程上的一個方法(AOP的核心功能就是植入代碼,在點和點之間加入代碼)

切入點 pointcut  ,它是一個描述,描述連接點是怎樣的連接,在連接點的前還是後切入,等等。切入點有個表達式,這樣寫:

切入點表達式:public String com.bjsxt.dao.*.add() 此表達式是用來描述一堆方法,是所有包下的add方法 

     public String com.bjsxt.dao.*.*();        此表達式是說描述所有包下的所有方法

通     知Advice    ,是在某個特定的連接點上執行的動作。包括before前置通知,after後置通知 和 around環繞通知

切     面Aspect    ,連接點、切入點、通知三者合一切爲一個切面。

目標對象Target Object,是你“切”哪個對象,相當於委託類

植入Weaving,製作代理的過程



小總結

JoinPoint連接點:業務流程當中的方法調用(普通的方法調用)

PointCut 切入點:利用一個表達式,描述多個連接點,將來會把代碼植入到一些連接點上面(在配置文件中配置要切哪些方法)

Advice 通知:增強功能代碼(代理類)

Aspect 切面

Target Object目標對象:委託類

Weaving 植入:製作代理的過程(Spring AOP製作代理類有兩種方式:proxy,cglib,當你的類有接口用proxy,沒有接口用cglib)



AOP實例代碼——————————————

1.導入jar包

commons-loggin.jar

spring.jar

aspectjrt.jar(是面向切面編程的實現包,非spring原生,第三方,spring在它的基礎上進行了封裝,讓用戶使用更加便利)

aspectjweaver.jar

cglib-nodep-2.1.3.jar

spring-sources.jar


2.配置用xml方式,把所有的bean放到xml中做切面

applicationcontext.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop 
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context   

http://www.springframework.org/schema/context/spring-context-2.5.xsd">

<!-- AOP功能是基於IOC容器的。AOP只能給IOC容器內部的對象做代理。AOP這把刀只能切IOC容器中的對象 -->

<!-- 這裏是把容器中的對象配置到容器當中,如下-->

<bean id="userDao"  class="com.bjsxt.dao.UserDao"></bean>

<bean id="userAction" class="com.bjsxt.action.UserAction" >

<property name="userDao"  ref="userDao" ></property>

</bean>

<bean id="logAdvice"  class="com.bjsxt.advice.LogAdvice" ></bean>

<bean id="teacherDao"  class="com.bjsxt.dao.TeacherDao" ></bean> <!--假如我是從項目中途加入的,另的aop不知道,可以直接寫我自己的teacherDao。在Test.java中也要相應做修改-->

<bean id="myClassDao"  class="com.bjsxt.dao.MyClassDaoImpl" ></bean>  <!--這個程序員依然不知道前面人員寫了什麼,就這樣加bean,這樣是可以的,此bean對應下面的MyClassDaoImpl.java-->

<!--這裏aop的配置如果註釋掉,那麼增強的功能將不會顯示,太強了!相當於一個開關!spring果然強大-->

<!--這裏定義切入點,連接點和通知的,有了這三樣,就開始定義切面-->

<aop:config>

<aop:pointcut  expression="execution(public * com.bjsxt.dao.*.*())"   id="logCut" /> <!--這裏是切入點,連接點就是已有的方法-->

<aop:aspect  ref="logAdvice" >  <!--通知,我們要增強的行爲,這對應的是一個類LogAdvice.java,上面的bean有定義,相當於代理類-->

<aop:before  method="aaa"  pointcut-ref="logCut" />

<aop:after  method="ccc"  pointcut-ref="logCut" />

</aop:aspect>

</aop:config>

<!--AOP增強功能到這-->

</beans>



3.LogAdvice.java

public class LogAdvice{

public void aaa(){

System.out.println("委託類方法執行之前執行!!!");

}

public void ccc(){

System.out.println("委託類方法執行之後!!!");

}

}



4.Test.java

   執行這個方法測試,這個test測試類就是客戶類

   public class Test{

public static void main(String[ ]  args){

ApplicationContext ac = new ClassPathXmlApplicationContext(

new String[ ] {"applicationContext.xml"}

);

//測試代碼一,測試一的時候把二、三註釋掉

UserDao userDao = (UserDao) ac.getBean("userDao");

userDao.add();


//測試代碼二,假定下面是你加入團隊後新加的代碼(練習時可註釋掉)

TeacherDao teacherDao = (TeacherDao)  ac.getBean("teacherDao");

System.out.println(teacherDao.getClass().getName);

teacherDao.add();

//end


//測試代碼三

MyClassDao myClassDao = (MyClassDao)  ac.getBean("myClassDao");

System.out.println(myClassDao.getClass().getName());

myClassDao.add();

myClassDao.del(); //如果執行結果只增強了add,而沒有增強del方法,看看配置文件中aop的地方,com.bjsxt.dao.*.*()還是隻*.add()

}

   }




5.dao包下面建立接口MyClassDao.java

public interface MyClassDao{

void add();

void del();

}



6.dao包下面寫實現類MyClassDaoImpl.java

public class MyClassDaoImpl  implements MyClassDao{

public void add(){

System.out.println("MyClassDaoImpl.add()");

}

public void del(){

System.out.println("MyClassDaoImpl.del()");

}

}


———————示例end———————————————





通知的類型

1.前置通知  在某連接點之前執行的通知,但這個通知不能阻止連接點前的執行(除非它招聘一個異常)

2.返回後通知  在某連接點正常完成後執行的通知

3.拋出異常後通知  在方法拋出異常退出時執行的通知

4.後通知  當某連接點退出的時候執行的通知

5.環繞通知  包圍一個連接點的通知,如方法調用。這是最強大的一種通知類型。環繞通知可以在方法調用前後完成自定義的行爲。環繞通知相當於filter,前後都可以攔截,環      繞通知相當於前置通知+返回後通知,不同的需求,使用的通知不一樣。


代碼

LogAdvice.java

public class LogAdvice{

public void aaa(){

System.out.println("委託方法執行之前!!!");

}

public void ccc(){

System.out.println("委託方法執行之後!!!");

}

public Object around(ProceedingJoinPoint pjp){ //正在執行的JoinPoint連接點,意味着這個環繞通知環繞在正在執行的連接點(方法)外。pjp就是在攔截,或者是代理過程中,爲通知,提供必要數據的抽象對象。有了數據後,就可以進行你想的操作了。pjp很重要。

System.out.println("委託類方法執行之前 !!!");

try{

//pjp.getArgs();  //獲取客戶類調用方法時,傳遞的參數

//pjp.getSignature().getName(); //獲取客戶類調用的方法的名字

//pjp.getTarget();    //獲取委託類

System.out.println("委託類方法執行之前!!!");

Object result = pjp.proceed(); //和chain.doFilter()是一樣的。

System.out.println("委託類方法執行之後!!!");

return result;

} catch(Throwable e) {

e.printStackTrace();

return null;

}

}

}


applicationContext.xml和上一個示例的一樣,需要注意的重點如下

<aop:config>

<aop:pointcut  expression = "execution ( public * com.bjsxt.dao.*.*() )"  id="logCut" />

<aop:aspect  ref="logAdvice" >

<aop:around  method="around"  pointcut-ref="logCut" />

</aop:aspect>

</aop:config>


————————示例代碼end——————————————



數據+算法=程序

代理模式,責任鏈模式,裝飾器模式它們很相似,但是各自有側重點

代理模式重在訪問控制

責任鏈模式重在信息過濾

裝飾器模式重在功能增強   在IO流中有體現,buffer


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章