欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring AOP入門Demo分享

 更新時間:2017年12月05日 11:30:42   作者:kite___  
這篇文章主要介紹了Spring AOP入門Demo分享,涉及創(chuàng)建maven項目,編寫切面類,通過bean配置關(guān)聯(lián)等相關(guān)內(nèi)容,具有一定借鑒價值,需要的朋友可以參考下。

在閱讀本文之前,大家可先行參閱簡單理解Spring之IOC和AOP及代碼示例一文,簡單了解下ioc和aop的相關(guān)內(nèi)容。下面進(jìn)入正題。

本文將會一步一步創(chuàng)建一個最簡單的例子,來使用Spring的AOP特性,算是一個Spring AOP的入門Demo。作為一個初學(xué)者,運行出這么簡單的一個Demo也踩了很多的坑。

OOP的問題,AOP的補充

當(dāng)我們需要為分散的對象引入公共行為的時候,OOP則顯得無能為力。也就是說,OOP允許你定義從上到下的關(guān)系,但并不適合定義從左到右的關(guān)系。例如日志功能。日志代碼往往水平地散布在所有對象層次中,而與它所散布到的對象的核心功能毫無關(guān)系。對于其他類型的代碼,如安全性、異常處理和透明的持續(xù)性也是如此。這種散布在各處的無關(guān)的代碼被稱為橫切(cross-cutting)代碼,在OOP設(shè)計中,它導(dǎo)致了大量代碼的重復(fù),而不利于各個模塊的重用。

所謂“方面”,簡單地說,就是將那些與業(yè)務(wù)無關(guān),卻為業(yè)務(wù)模塊所共同調(diào)用的邏輯或責(zé)任封裝起來,便于減少系統(tǒng)的重復(fù)代碼,降低模塊間的耦合度,并有利于未來的可操作性和可維護(hù)性。

Spring中對AOP的支持

Spring中AOP代理由Spring的IoC容器負(fù)責(zé)生成、管理,其依賴關(guān)系也由IoC容器負(fù)責(zé)管理。因此,AOP代理可以直接使用容器中的其他Bean實例作為目標(biāo),這種關(guān)系可由IoC容器的依賴注入提供。Spring默認(rèn)使用Java動態(tài)代理來創(chuàng)建AOP代理,這樣就可以為任何接口實例創(chuàng)建代理了。當(dāng)需要代理的類不是代理接口的時候,Spring自動會切換為使用CGLIB代理,也可強制使用CGLIB。

本例子的邏輯如下:有一個Car類(業(yè)務(wù)類),在Car類中的go方法運行之前和之后,都會有相應(yīng)的日志記錄,但Car類本身并不知道日志的任何邏輯。

創(chuàng)建Maven項目并添加依賴

首先,新建一個Maven項目,使用 maven‐archetype‐quickstart模板,然后打開pom.xml文件,加入Spring AOP運行需要的依賴包

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>4.0.5.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-beans</artifactId>
  <version>4.0.5.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>4.0.5.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>4.0.5.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.8.1</version>
</dependency>

編寫業(yè)務(wù)代碼

新增一個業(yè)務(wù)類Car,包含一個go()方法

package com.wowo.spring_aop_demo1;
public class Car {
  public void go(){
    System.out.println("go go go!");
  }
}

編寫切面類

日志類會記錄下系統(tǒng)的運行情況,但日志的邏輯不會在業(yè)務(wù)類中寫的到處都是,而是作為一個切面類存在。

package com.wowo.spring_aop_demo1;
public class CarLogger {
  public void beforeRun(){
    System.out.println("car is going to run");
  }
  public void afterRun(){
    System.out.println("car is running");
  }
}

該切面類包含兩個方法,他們分別是前置通知和后置通知。

通過bean來配置關(guān)聯(lián)

新增一個配置文件,本例命名為bean.xml,在配置文件中來關(guān)聯(lián)切面與通知

<?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-2.5.xsd
      http://www.springframework.org/schema/context 
      http://www.springframework.org/schema/context/spring-context-2.5.xsd
      http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop.xsd"
  >
  <bean id="car" class="com.wowo.spring_aop_demo1.Car"/>
  <bean id="logger" class="com.wowo.spring_aop_demo1.CarLogger" />
  <aop:config>
    <aop:aspect ref="logger">
      <aop:pointcut expression="execution(* com.wowo.spring_aop_demo1.Car.go(..))" id="go"/>

      <aop:before pointcut-ref="go" method="beforeRun" />
      <aop:after pointcut-ref="go" method="afterRun" />
    </aop:aspect>
  </aop:config>
</beans>

注意:這個配置文件中,aop的命名空間,以及xsi:schemaLocation中包含的幾個地址都是必須的。
execution(* com.wowo.spring_aop_demo1.Car.go(..))是一個AspectJ切點表達(dá)式,execution表示在執(zhí)行時觸發(fā),后面的*表示任意類型的返回值,com.wowo.spring_aop_demo1.Car指的是切點所在的類,go(..)是方法名,..表示任意參數(shù)。

Spring切面可以應(yīng)用5種類型的通知:

·Before——在方法被調(diào)用之前調(diào)用通知
·After——在方法完成之后調(diào)用通知,無論方法是否執(zhí)行成功
·After-returning——在方法成功執(zhí)行之后調(diào)用通知
·After-throwing——在方法拋出異常后調(diào)用通知
·Around——通知包裹了被通知的方法,在被通知的方法調(diào)用之前和調(diào)用之后都執(zhí)行自定義的行為

運行業(yè)務(wù)代碼

下面創(chuàng)建一個包含main()方法的類,來運行業(yè)務(wù)代碼

package com.wowo.spring_aop_demo1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App 
{
  public static void main( String[] args )
  {
    ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
    Car car=(Car) context.getBean("car");
    car.go();
  }
}

在上面的代碼中,由Spring創(chuàng)建了一個car對象。Spring在創(chuàng)建該對象時,發(fā)現(xiàn)它的一個方法被配置成了切點(pointcut),所以,在實例化該對象時,會創(chuàng)建一個代理對象,當(dāng)切點方法go()執(zhí)行時,會被Spring創(chuàng)建的代理對象所攔截,運行g(shù)o方法之前,會調(diào)用所對應(yīng)的切面類CarLogger的前置方法beforeRun(),然后調(diào)用Car.go()方法,再然后就調(diào)用切面類CarLogger的后置方法afterRun()。

注意:必須使用Spring創(chuàng)建包含切點的對象,如果自己創(chuàng)建的話,Spring是監(jiān)測不到的,它的運行也不會被應(yīng)用任何通知。

項目輸出結(jié)果為

car is going to run
go go go!
car is running

使用環(huán)繞通知

如果想使用環(huán)繞通知,我們需要修改切面類中的通知方法以及配置文件,業(yè)務(wù)類無需做任何修改,因為他們是完全解耦的。首先修改切面類CarLogger

import org.aspectj.lang.ProceedingJoinPoint;
public class CarLogger {

  public void aroundRun(ProceedingJoinPoint joinpoint){
    System.out.println("car is going to run");
    try {
      //調(diào)用被代理的對象的目標(biāo)方法,本例中指向Car.go()方法
      joinpoint.proceed();
    } catch (Throwable e) {
      e.printStackTrace();
    }
    System.out.println("car is running");
  }
}

環(huán)繞通知的方法,需要接受ProceedingJoinPoint類型的參數(shù),其proceed()方法將會調(diào)用被代理對象的目標(biāo)方法,所以,正常情況下,這個方法一定要調(diào)用。我們也可以通過不調(diào)用該方法來組織被代理對象的運行。

接下來將配置文件的aop:config部分修改為如下所示

<aop:config>
    <aop:aspect ref="logger">
      <aop:pointcut expression="execution(* com.wowo.spring_aop_demo1.Car.go(..))" id="go"/>
      <aop:around method="aroundRun" pointcut-ref="go"/>
    </aop:aspect>
  </aop:config>

注意:環(huán)繞通知不能和前置/后置通知同時存在。運行代碼后,輸出結(jié)果不變。

總結(jié)

以上就是本文關(guān)于Spring AOP入門Demo分享的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!

相關(guān)文章

  • 學(xué)好Java?MyBatis攔截器,提高工作效率

    學(xué)好Java?MyBatis攔截器,提高工作效率

    這篇文章主要介紹了Java中的?MyBatis攔截器,??Mybatis攔截器設(shè)計的初衷就是為了供用戶在某些時候可以實現(xiàn)自己的邏輯而不必去動Mybatis固有的邏輯。詳細(xì)內(nèi)容需要的小伙伴可以參考下面文章內(nèi)容,希望對你有所幫助
    2022-02-02
  • java可變參數(shù)使用示例

    java可變參數(shù)使用示例

    這篇文章主要介紹了java可變參數(shù)使用示例,需要的朋友可以參考下
    2014-04-04
  • java實現(xiàn)動態(tài)代理方法淺析

    java實現(xiàn)動態(tài)代理方法淺析

    這篇文章主要介紹了java實現(xiàn)動態(tài)代理方法淺析,很實用的功能,需要的朋友可以參考下
    2014-08-08
  • java監(jiān)聽器的實現(xiàn)和原理詳解

    java監(jiān)聽器的實現(xiàn)和原理詳解

    這篇文章主要給大家介紹了關(guān)于java監(jiān)聽器實現(xiàn)和原理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • java檢查服務(wù)器的連通兩種方法代碼分享

    java檢查服務(wù)器的連通兩種方法代碼分享

    這篇文章主要介紹了java檢查服務(wù)器的連通兩種方法代碼分享,涉及ping的介紹以及檢查服務(wù)器連通的兩種方法代碼示例,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • 關(guān)于ApplicationContext的三個常用實現(xiàn)類

    關(guān)于ApplicationContext的三個常用實現(xiàn)類

    這篇文章主要介紹了關(guān)于ApplicationContext的三個常用實現(xiàn)類,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • 老生常談java中的fail-fast機制

    老生常談java中的fail-fast機制

    下面小編就為大家?guī)硪黄仙U刯ava中的fail-fast機制。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • springboot如何讀取sftp的文件

    springboot如何讀取sftp的文件

    這篇文章主要介紹了springboot如何讀取sftp的文件,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java線程創(chuàng)建與Thread類的使用方法

    Java線程創(chuàng)建與Thread類的使用方法

    這篇文章主要介紹了Java線程創(chuàng)建與Thread類的使用方法,圍繞java多線程中Thread類的使用以及有關(guān)線程對象創(chuàng)建和常用方法的相關(guān)資料展開詳細(xì)內(nèi)容,具有一定的參考價值,需要的下伙伴可以參考一下
    2022-06-06
  • Java使用Gateway自定義負(fù)載均衡過濾器

    Java使用Gateway自定義負(fù)載均衡過濾器

    這篇文章主要介紹了Java使用Gateway自定義負(fù)載均衡過濾器,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07

最新評論