一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|JavaScript|易語(yǔ)言|

服務(wù)器之家 - 編程語(yǔ)言 - JAVA教程 - Spring AOP入門(mén)Demo分享

Spring AOP入門(mén)Demo分享

2021-02-27 14:09kite___ JAVA教程

這篇文章主要介紹了Spring AOP入門(mén)Demo分享,涉及創(chuàng)建maven項(xiàng)目,編寫(xiě)切面類(lèi),通過(guò)bean配置關(guān)聯(lián)等相關(guān)內(nèi)容,具有一定借鑒價(jià)值,需要的朋友可以參考下。

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

本文將會(huì)一步一步創(chuàng)建一個(gè)最簡(jiǎn)單的例子,來(lái)使用SpringAOP特性,算是一個(gè)Spring AOP的入門(mén)Demo。作為一個(gè)初學(xué)者,運(yùn)行出這么簡(jiǎn)單的一個(gè)Demo也踩了很多的坑。

OOP的問(wèn)題,AOP的補(bǔ)充

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

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

Spring中對(duì)AOP的支持

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

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

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

首先,新建一個(gè)Maven項(xiàng)目,使用 maven‐archetype‐quickstart模板,然后打開(kāi)pom.xml文件,加入Spring AOP運(yùn)行需要的依賴(lài)包

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<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>

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

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

?
1
2
3
4
5
6
package com.wowo.spring_aop_demo1;
public class Car {
  public void go(){
    System.out.println("go go go!");
  }
}

編寫(xiě)切面類(lèi)

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

?
1
2
3
4
5
6
7
8
9
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");
  }
}

該切面類(lèi)包含兩個(gè)方法,他們分別是前置通知和后置通知。

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?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>

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

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

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
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)建了一個(gè)car對(duì)象。Spring在創(chuàng)建該對(duì)象時(shí),發(fā)現(xiàn)它的一個(gè)方法被配置成了切點(diǎn)(pointcut),所以,在實(shí)例化該對(duì)象時(shí),會(huì)創(chuàng)建一個(gè)代理對(duì)象,當(dāng)切點(diǎn)方法go()執(zhí)行時(shí),會(huì)被Spring創(chuàng)建的代理對(duì)象所攔截,運(yùn)行g(shù)o方法之前,會(huì)調(diào)用所對(duì)應(yīng)的切面類(lèi)CarLogger的前置方法beforeRun(),然后調(diào)用Car.go()方法,再然后就調(diào)用切面類(lèi)CarLogger的后置方法afterRun()。

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

項(xiàng)目輸出結(jié)果為

?
1
2
3
car is going to run
go go go!
car is running

使用環(huán)繞通知

如果想使用環(huán)繞通知,我們需要修改切面類(lèi)中的通知方法以及配置文件,業(yè)務(wù)類(lèi)無(wú)需做任何修改,因?yàn)樗麄兪峭耆怦畹摹J紫刃薷那忻骖?lèi)CarLogger

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import org.aspectj.lang.ProceedingJoinPoint;
public class CarLogger {
 
  public void aroundRun(ProceedingJoinPoint joinpoint){
    System.out.println("car is going to run");
    try {
      //調(diào)用被代理的對(duì)象的目標(biāo)方法,本例中指向Car.go()方法
      joinpoint.proceed();
    } catch (Throwable e) {
      e.printStackTrace();
    }
    System.out.println("car is running");
  }
}

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

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

?
1
2
3
4
5
6
<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)繞通知不能和前置/后置通知同時(shí)存在。運(yùn)行代碼后,輸出結(jié)果不變。

總結(jié)

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

原文鏈接:http://blog.csdn.net/daguanjia11/article/details/49278003

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久国产精品永久免费网站 | 亚洲免费在线看 | 国产成人精品本亚洲 | 欧美一区二区三区高清不卡tv | 国色天香社区视频免费高清在线观看 | 国产玖玖在线 | avtt天堂在线| 四虎tv| 亚洲日韩男人网在线 | 男人影院天堂网址 | 亚洲mv国产精品mv日本mv | 含羞草国产亚洲精品岁国产精品 | 亚洲系列国产系列 | 青青草伊人久久 | 色老板影视 | 2020国产精品视频 | 美女扒开屁股让我桶免费 | 欧美一区二区三区视视频 | 精品国产精品人妻久久无码五月天 | 国产精品久久久久久久久ktv | xxxx俄罗斯大白屁股 | 欧美日韩精品一区二区三区视频在线 | 91精品国产免费久久国语蜜臀 | 日韩在线视频免费观看 | 午夜香蕉成视频人网站高清版 | free service性v极品 | 亚洲视频在线一区二区三区 | 国产成人免费在线观看 | 日本国产最新一区二区三区 | 色爱导航 | 午夜AV内射一区二区三区红桃视 | 国产成人欧美视频在线 | 精品网站一区二区三区网站 | 午夜黄视频 | 好大好猛好爽好深视频免费 | 欧美一级视频免费观看 | 爱情岛论坛亚洲自拍 | 脱jk裙的美女露小内内无遮挡 | 亚洲国产黄色 | pornohd老师18| 精品国语对白精品自拍视 |