国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

貓頭鷹的深夜翻譯:使用SpringBoot和AspectJ實現(xiàn)AOP

meislzhua / 1837人閱讀

摘要:我們會寫切面來攔截對這些業(yè)務(wù)類和類的調(diào)用。切面定義何時攔截一個方法以及做什么和在一起成為切面連接點當(dāng)代碼開始執(zhí)行,并且切點的條件滿足時,通知被調(diào)用。

前言

這篇文章會幫助你使用Spring Boot Starter AOP實現(xiàn)AOP。我們會使用AspectJ實現(xiàn)四個不同的通知(advice),并且新建一個自定義的注解來追蹤方法的執(zhí)行時間。

你將會了解

什么是交叉分割關(guān)注點(cross-cutting concern)?

在應(yīng)用中你如何實現(xiàn)交叉分割關(guān)注點?

   - 如果你想要將對web應(yīng)用所有的訪問請求記入日志,你能想到什么方法?
   - 如果你想追蹤每個請求的性能,你能想到什么方法?

AOP中的切面(Aspects)和切點(Pointcut)是什么?

有哪些不同類型的AOP通知(advice)?

如何使用Spring Boot實現(xiàn)AOP?

如何使用Spring AOP和AspectJ實現(xiàn)切面?

有哪些AOP最佳實踐?

項目代碼結(jié)構(gòu)

下圖是我們即將創(chuàng)建的項目結(jié)構(gòu)的截圖:

一些細節(jié):

SpringBootTutorialBasicsApplication.java: 由Spring Initializer初始化生成的Spring Boot應(yīng)用類。這個類是應(yīng)用啟動類。

pom.xml: 創(chuàng)建項目所需的全部依賴。我們將會使用Spring Boot Starter AOP依賴。

Business1.java, Business2.java, Dao1.java, Dao2.java: 業(yè)務(wù)類依賴于Dao類。我們會寫切面來攔截對這些業(yè)務(wù)類和DAO類的調(diào)用。

AfterAopAspect.java: 實現(xiàn)一些After通知。

UserAccessAspect.java: 實現(xiàn)一個Before通知,用來做訪問權(quán)限檢查

BusinessAopSpringBootTest.java:對業(yè)務(wù)方法進行單元測試

Maven3.0+:編譯工具

Eclipse: 開發(fā)工具

JDK1.8+

源碼Github地址
介紹AOP

應(yīng)用通常劃分為多個層進行開發(fā),一個經(jīng)典的JAVA應(yīng)用有:

網(wǎng)絡(luò)層:用REST或是應(yīng)用的形式將服務(wù)暴露給外部使用

業(yè)務(wù)層:業(yè)務(wù)邏輯

數(shù)據(jù)層:數(shù)據(jù)持久化邏輯

雖然各個層的職責(zé)不同,但是每個層之間也有一些共通的地方

日志

安全

這些共通的切面成為交叉分割關(guān)注點(cross-cutting-concerns)

實現(xiàn)交叉分割關(guān)注點的一個方法是在每一個層分貝進行實現(xiàn)。但是,這樣會使得代碼難以維護。

面向切面編程為實現(xiàn)交叉分割關(guān)注點提供了一個解決方案:

將交叉分割切入點實現(xiàn)為一個切面

定義切點,說明這些切面在何時調(diào)用

這樣確保了交叉分割關(guān)注點定義在一個內(nèi)聚的代碼組件中,并且能夠在需要的時候使用。

初始化Spring Boot AOP項目

使用Spring Initializer新建一個Spring AOP項目非常的方法。

Spring Initializer是創(chuàng)建Spring Boot項目的超級棒的工具。

備注:

啟動Spring Initializer并且選擇一下內(nèi)容

選擇com.in28minutes.springboot.tutorial.basics.example為Group

選擇 spring-boot-tutorial-basics為Artifact

選擇AOP依賴

點擊Generate Project

將項目導(dǎo)入Eclipse

Spring Boot AOP starter

Spring Boot AOP Starter的關(guān)鍵依賴有:

Spring AOP提供的基本的AOP功能

AspectJ提供的完整的AOP框架


    org.springframework
    spring-aop
    5.0.1.RELEASE
    compile


    org.aspectj
    aspectjweaver
    1.8.12
    compile
配置AOP

讓我們添加一些業(yè)務(wù)邏輯類 - Business1和Business2。這些業(yè)務(wù)邏輯類依賴于一組數(shù)據(jù)類 - Data1和Data2。

@Service
public class Business1 {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private Dao1 dao1;
    public String calculateSomething() {
        String value = dao1.retrieveSomething();
        logger.info("In Business - {}", value);
        return value;
    }
}
@Service
public class Business2 {
    @Autowired
    private Dao2 dao2;
    public String calculateSomething() {
        //Business Logic
        return dao2.retrieveSomething();
    }
}
@Repository
public class Dao1 {
    public String retrieveSomething() {
        return "Dao1";
    }
}
@Repository
public class Dao2 {
    public String retrieveSomething() {
        return "Dao2";
    }
}

備注:

@Autowired private Dao1 dao1: DAO作為依賴注入業(yè)務(wù)類中

public String calculateSomething(): 每個業(yè)務(wù)類包含一個簡單的calculate方法

一個簡單的AOP單元測試

讓我們寫一個簡單的單元測試來調(diào)用剛剛創(chuàng)建的業(yè)務(wù)類:

@RunWith(SpringRunner.class)
@SpringBootTest
public class BusinessAopSpringBootTest {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private Business1 business1;
    @Autowired
    private Business2 business2;
    @Test
    public void invokeAOPStuff() {
        logger.info(business1.calculateSomething());
        logger.info(business2.calculateSomething());
    }
}

備注:

@RunWith(SpringRunner.class) @SpringBootTest public class BusinessAopSpringBootTest:: 我們將在單元測試用啟動一個完整的Spring Boot應(yīng)用

@Autowired private Business1 business1@Autowiredprivate Business2 business2: 將業(yè)務(wù)類注入啟動測試的Spring上下文中

@Test public void invokeAOPStuff(){...}: 調(diào)用業(yè)務(wù)層的方法

這時,我們沒有實現(xiàn)任何的AOP邏輯,因此,測試的輸出應(yīng)該就是從DAO類和業(yè)務(wù)類中返回的簡單的信息:

c.i.s.t.b.e.a.BusinessAopSpringBootTest  : In Business - Dao1
c.i.s.t.b.e.a.BusinessAopSpringBootTest  : Dao1
實現(xiàn)@Before通知

通常來講,當(dāng)我們使用AOP來實現(xiàn)安全時,我們會想要攔截對方法的調(diào)用并進行檢查。這可以直接通過@Before通知實現(xiàn)。

下面給出了一種實現(xiàn):

@Aspect
@Configuration
public class UserAccessAspect {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    //What kind of method calls I would intercept
    //execution(* PACKAGE.*.*(..))
    //Weaving & Weaver
    @Before("execution(* com.in28minutes.springboot.tutorial.basics.example.aop.data.*.*(..))")
    public void before(JoinPoint joinPoint) {
        //Advice
        logger.info(" Check for user access ");
        logger.info(" Allowed execution for {}", joinPoint);
    }
}

備注:

@Aspect: 說明這是一個切面

@Configuration: 說明這是一個對切面的Spring Bean配置

@Before: 我們想要在方法執(zhí)行前執(zhí)行切面

("execution(* com.in28minutes.springboot.tutorial.basics.example.aop.data.*.*(..))": 定義了切點。我們想要攔截com.in28minutes.springboot.tutorial.basics.example.aop.data包中的所有方法。

當(dāng)我們運行單元測試時,你會看見,在執(zhí)行DAO方法之前,會執(zhí)行用戶權(quán)限檢查:

Check for user access 
Allowed execution for execution(String com.in28minutes.springboot.tutorial.basics.example.aop.data.Dao1.retrieveSomething())
c.i.s.t.b.e.a.BusinessAopSpringBootTest  : In Business - Dao1
c.i.s.t.b.e.a.BusinessAopSpringBootTest  : Dao1
Check for user access 
Allowed execution for execution(String com.in28minutes.springboot.tutorial.basics.example.aop.data.Dao2.retrieveSomething())
c.i.s.t.b.e.a.BusinessAopSpringBootTest  : Dao2
理解AOP術(shù)語: Pointcut, Advice, Aspect,Join Point

讓我們花點時間來了解一下AOP術(shù)語:

切點(Pointcut):該表達式用來定義何時方法應(yīng)當(dāng)被攔截。在上例中,切點為`execution(* com.in28minutes.springboot.tutorial.basics.

example.aop.data..(..))`。

通知(Advice):你想要做什么?一個通知是你在攔截方法時想要調(diào)用的邏輯。在上例中,通知為before(JoinPoint joinPoint)方法中的代碼。

切面(Aspect):定義何時攔截一個方法(Pointcut)以及做什么(Advice)和在一起成為切面

連接點(Join Point):當(dāng)代碼開始執(zhí)行,并且切點的條件滿足時,通知被調(diào)用。連接點是一個通知運行的特定實例。

織如(Weaver):實現(xiàn)AOP的框架 - AspectJ或Spring AOP

使用@After, @AfterReturning和@AfterThrowing通知

讓我們現(xiàn)在來看看AOP提供的別的攔截選項:

@After: 在兩種場景下執(zhí)行 - 當(dāng)一個方法成功執(zhí)行或是拋出異常

@AfterReturning: 只有在方法成功執(zhí)行后運行

@AfterThrowing: 只有在方法拋出異常后運行

讓我們創(chuàng)建一個包含這些元素的簡單的切面:

@Aspect
@Configuration
public class AfterAopAspect {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @AfterReturning(value = "execution(* com.in28minutes.springboot.tutorial.basics.example.aop.business.*.*(..))",
        returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        logger.info("{} returned with value {}", joinPoint, result);
    }
    @After(value = "execution(* com.in28minutes.springboot.tutorial.basics.example.aop.business.*.*(..))")
    public void after(JoinPoint joinPoint) {
        logger.info("after execution of {}", joinPoint);
    }
}

執(zhí)行后運行結(jié)果如下所示:

Check for user access 
Allowed execution for execution(String com.in28minutes.springboot.tutorial.basics.example.aop.data.Dao1.retrieveSomething())
In Business - Dao1
after execution of execution(String com.in28minutes.springboot.tutorial.basics.example.aop.business.Business1.calculateSomething())
execution(String com.in28minutes.springboot.tutorial.basics.example.aop.business.Business1.calculateSomething()) returned with value Dao1
c.i.s.t.b.e.a.BusinessAopSpringBootTest  : Dao1
Check for user access 
Allowed execution for execution(String com.in28minutes.springboot.tutorial.basics.example.aop.data.Dao2.retrieveSomething())
after execution of execution(String com.in28minutes.springboot.tutorial.basics.example.aop.business.Business2.calculateSomething())
execution(String com.in28minutes.springboot.tutorial.basics.example.aop.business.Business2.calculateSomething()) returned with value Dao2
c.i.s.t.b.e.a.BusinessAopSpringBootTest  : Dao2

可以看到,就在將值返回給調(diào)用的業(yè)務(wù)邏輯之前,after通知被執(zhí)行了。

其它AOP功能:@Around和注解

能夠使用AOP實現(xiàn)的功能之一是通過自定義注釋來解析方法調(diào)用。

下面的例子展示了一個簡單的TrackTiem注釋:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TrackTime {

我們可以添加一個切面來定義當(dāng)添加TrackTime注解以后執(zhí)行的邏輯。MethodExecutionCalculationAspect實現(xiàn)了一個簡單的時間追蹤功能。

@Aspect
@Configuration
public class MethodExecutionCalculationAspect {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Around("@annotation(com.in28minutes.springboot.tutorial.basics.example.aop.TrackTime)")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        joinPoint.proceed();
        long timeTaken = System.currentTimeMillis() - startTime;
        logger.info("Time Taken by {} is {}", joinPoint, timeTaken);
    }
}

備注:

@Around: 是一個環(huán)繞型通知。它攔截方法調(diào)用后使用joinPoint.proceed()來執(zhí)行方法

@annotation(com.in28minutes.springboot.tutorial.basics.example.aop.TrackTime): 基于注解進行攔截的切點 - @annotation緊跟著完整的注解的名稱

定義了注解和通知之后,我們可以將注解運用到想要跟蹤的方法上,如下所示:

@Service
public class Business1 {
    @TrackTime
    public String calculateSomething(){
AOP最賤實踐

AOP最佳實踐之一是將所有的切點定義在一個類中。這樣有利于在一個地方維護所有的切點。

public class CommonJoinPointConfig {
    @Pointcut("execution(* com.in28minutes.spring.aop.springaop.data.*.*(..))")
    public void dataLayerExecution() {}
    @Pointcut("execution(* com.in28minutes.spring.aop.springaop.business.*.*(..))")
    public void businessLayerExecution() {}
}

在定義其它切面的切入點時,可以這樣調(diào)用上面的定義:

@Around("com.in28minutes.spring.aop.springaop.aspect.CommonJoinPointConfig.businessLayerExecution()")

完整的代碼請前往GITHUB瀏覽


想要了解更多開發(fā)技術(shù),面試教程以及互聯(lián)網(wǎng)公司內(nèi)推,歡迎關(guān)注我的微信公眾號!將會不定期的發(fā)放福利哦~

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/76317.html

相關(guān)文章

  • 頭鷹深夜翻譯:為什么要使用Spring Boot?

    摘要:初次使用的人往往會困惑,不知道該使用哪種方法。目前來說,團隊推薦使用基于的方法來提供更高的靈活性。配置,從而在應(yīng)用啟動時執(zhí)行腳本來初始化數(shù)據(jù)庫。目前為止我們沒有任何消息需要配置,所以只在文件夾中創(chuàng)建一個空的文件。將配置為,它包含的上下文。 前言 spring是一個用于創(chuàng)建web和企業(yè)應(yīng)用的一個很流行的框架。和別的只關(guān)注于一點的框架不同,Spring框架通過投資并組合項目提供了大量的功能...

    Jaden 評論0 收藏0
  • 頭鷹深夜翻譯:在JVM上根據(jù)合約編程

    摘要:前言這周我準(zhǔn)備介紹一個有趣的但是很少使用的方法按照合約編程,又稱為合約編程,是一種軟件設(shè)計的方法。這些規(guī)則被稱為合約,可以比擬為商業(yè)合同中的條件和義務(wù)。通過將檢查和異常拋出指令包裝到方法中,人們可以很容易地實現(xiàn)合約式編程。 前言 這周我準(zhǔn)備介紹一個有趣的但是很少使用的方法 按照合約編程,又稱為合約編程,是一種軟件設(shè)計的方法。它規(guī)定了軟件設(shè)計師應(yīng)該為軟件組件定義正式,精確和可驗證的接口規(guī)...

    whatsns 評論0 收藏0
  • 頭鷹深夜翻譯:Java WeakHashMap

    摘要:本文簡介類概覽類構(gòu)造器總結(jié)類構(gòu)造方法類使用舉例類概覽是一個實現(xiàn)了接口,并且鍵為型的哈希表。中的條目不再被正常使用時,會被自動刪除。它的鍵值均支持。和絕大多數(shù)的集合類一樣,這個類不是同步的。 本文簡介 WeakHashMap類概覽 WeakHashMap類構(gòu)造器總結(jié) WeakHashMap類構(gòu)造方法 WeakHasjMap類使用舉例 1. WeakHashMap類概覽 Wea...

    BothEyes1993 評論0 收藏0
  • 頭鷹深夜翻譯:JDK Vs. JRE Vs. JVM之間區(qū)別

    摘要:什么是為執(zhí)行字節(jié)碼提供一個運行環(huán)境。它的實現(xiàn)主要包含三個部分,描述實現(xiàn)規(guī)格的文檔,具體實現(xiàn)和滿足要求的計算機程序以及實例具體執(zhí)行字節(jié)碼。該類先被轉(zhuǎn)化為一組字節(jié)碼并放入文件中。字節(jié)碼校驗器通過字節(jié)碼校驗器檢查格式并找出非法代碼。 什么是Java Development Kit (JDK)? JDK通常用來開發(fā)Java應(yīng)用和插件?;旧峡梢哉J(rèn)為是一個軟件開發(fā)環(huán)境。JDK包含Java Run...

    blair 評論0 收藏0
  • 頭鷹深夜翻譯:Java中CAS(Compare And Swap)

    摘要:否則它就會用新的值替代當(dāng)前值。在這種情況下,鎖可能會優(yōu)于原子變量,但在實際的爭用級別中,原子變量的性能優(yōu)于鎖。在中引入了另外一個構(gòu)件。 題目要求 在我們深入了解CAS(Compare And Swap)策略以及它是如何在AtomicInteger這樣的原子構(gòu)造器中使用的,首先來看一下這段代碼: public class MyApp { private volatile int ...

    hosition 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<