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

java開發(fā)AOP面向切面編程入門

 更新時(shí)間:2021年10月13日 09:14:56   作者:guoyp2126  
這篇文章主要介紹了java開發(fā)的AOP面向切面編程入門的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步學(xué)有所得

引言

在實(shí)際應(yīng)用場(chǎng)景中,我們封裝一個(gè)學(xué)生的類,這個(gè)類用于封裝學(xué)生的日常行為,如:上學(xué)、吃飯、上課等。然而,在疫情期間,學(xué)生上學(xué)時(shí)入校、吃飯時(shí)進(jìn)入餐廳,需要測(cè)溫查驗(yàn)證件等行為,拿到這樣的需求我們?cè)趺崔k?

不好的解決方案

面向過程的解決方案

遇到問題解決問題,在上學(xué)、吃飯方法中加上測(cè)溫、查驗(yàn)證件方法,或者在學(xué)生類中提煉一個(gè)測(cè)溫查驗(yàn)證件私有的方法,在需要時(shí)調(diào)用。

代碼如下:

public class Student {
    public void toSchool(){
        check();
        System.out.println("高高興興去上學(xué)!");
    }
    public void toEat(){
        check();
        System.out.println("一號(hào)餐廳去吃飯!");
    }

    public void toClass(){
        System.out.println("排排坐,聽講座!");
    }

    public void getUp(){
        System.out.println("起床啦!");
    }
    
    private void check(){
        System.out.println("查驗(yàn)證件、測(cè)體溫");
    }
}

這種方式存在問題只是頭痛醫(yī)頭、腳痛醫(yī)腳,代碼硬拷貝,現(xiàn)在教師進(jìn)校門也要查驗(yàn)證件測(cè)溫,如何辦?將check代碼復(fù)制到教師類中,再者,如果check()中業(yè)務(wù)規(guī)則發(fā)生變化,則需要到處改代碼,顯然是一種非常蹩腳的解決方案。

使用繼承解決方案

創(chuàng)建一個(gè)man的基類,將check()方法放到該類中,教師、學(xué)生均繼承此類,子類調(diào)用這個(gè)方法即可,

代碼如下:

public class Man {
    protected void check(){
        System.out.println("查驗(yàn)證件、測(cè)體溫");
    }
}
public class Student extends Man {

    public void toSchool(){
        check();
        System.out.println("高高興興去上學(xué)!");
    }

    public void toEat(){
        check();
        System.out.println("一號(hào)餐廳去吃飯!");
    }
}

public class Teacher extends Man {
    public void toSchool(){
        check();
        System.out.println("高高興興去上班!");
    }

    public void toEat(){
        check();
        System.out.println("教工餐廳去吃飯!");
    }

    public void toClass(){
        System.out.println("排排坐,聽講座!");
    }
}

這種方式,雖然解決了代碼復(fù)制問題,但違背了面向?qū)ο蟪绦蛟O(shè)計(jì)的單一職責(zé)原則,因?yàn)椴轵?yàn)證件測(cè)溫等均不是學(xué)生或教師應(yīng)該擁有的職責(zé),類的劃分職責(zé)不清,增加了代碼擴(kuò)展維護(hù)的難度。

使用聚合的解決方案

將查驗(yàn)證件測(cè)溫等行為封裝一個(gè)獨(dú)立的類,學(xué)生和教師的依然只封裝他們固有的方法,

代碼如下:

public class Checktor {
    public void takeTemperature(){
        System.out.println("查驗(yàn)證件、測(cè)體溫");
    }
}
public class Student {
    private Checktor checktor = new Checktor();

    public void toSchool(){
        checktor.takeTemperature();
        System.out.println("高高興興去上學(xué)!");
    }

    public void toEat(){
        checktor.takeTemperature();
        System.out.println("一號(hào)餐廳去吃飯!");
    }
}

這種方法很好的解決了面向?qū)ο蟪绦蛟O(shè)計(jì)單一職責(zé)原則,體現(xiàn)了類的封裝性,但是代碼侵入性很強(qiáng),而且代碼僵化,維護(hù)性差。如疫情結(jié)束了,我們要求取消查驗(yàn)證件和測(cè)溫,就需要改原有的代碼,破壞了開閉原則,增加了程序員的工作量。有些人寫配置開關(guān)變量,在調(diào)用時(shí)使用ifelse進(jìn)行判斷是否調(diào)用也能遵循開關(guān)變量,但是代碼中包含了一些可能用不到代碼,不優(yōu)雅,不是很好解決方案。

面向切面的編程基本概念

面向切面的編程是不破壞原有類封裝性的前提下,動(dòng)態(tài)在其方法前面(before)、后邊(after)及周圍(Around)(前面和后邊)增強(qiáng)功能。

  • 連接點(diǎn)(Joinpoint):目標(biāo)對(duì)象中每個(gè)方法前面、后面均為連接點(diǎn)。如學(xué)生類中toSchool、toEat、toClass、getUp方法前面后面均是切入點(diǎn);
  • 切入點(diǎn)(Point):需要增強(qiáng)功能方法前面或后面,是切入點(diǎn),如進(jìn)學(xué)校前、吃飯前需要測(cè)體溫,則toSchool、toEat兩個(gè)方法前是切入點(diǎn),其余的不是;

在這里插入圖片描述

  • 切面類(Aspect):也稱通知類,封裝了需要增強(qiáng)功能的類,如:Checktor;
  • 通知方法(advice):需要增強(qiáng)的功能,如:測(cè)溫方法;
  • 通知類型:前置通知(Before)、后置通知(After)、環(huán)繞通知(around)、異常通知(throwing)、最終通知(after (finally) advice);

在這里插入圖片描述

  • 代理(proxy):將通知應(yīng)用到目標(biāo)對(duì)象實(shí)現(xiàn)機(jī)制,是通過創(chuàng)建代理對(duì)象完成的
  • 織入(Weaving):將切面代碼插入到目標(biāo)對(duì)象上,生成代理對(duì)象的過程

基于Spring面向切面程序?qū)崿F(xiàn)

針對(duì)學(xué)生上學(xué)場(chǎng)景,Spring的使用XML和注解兩設(shè)計(jì)種方式完成面向切面的編程。
工程依賴項(xiàng):在maven pom文件中,需要引入以下依賴項(xiàng)

     <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjtools</artifactId>
      <version>1.8.9</version>
    </dependency>

    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.5.4</version>
    </dependency>

    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.5</version>
      <scope>runtime</scope>
    </dependency>

XML方式:
學(xué)生類:

public class Student {

    public void toSchool(){
        System.out.println("高高興興去上學(xué)!");
    }

    public void toEat(){
        System.out.println("一號(hào)餐廳去吃飯!");
    }

    public void toClass(){
        System.out.println("排排坐,聽講座!");
    }

    public void getUp(){
        System.out.println("起床啦!");
    }
}

切面類:

public class Checktor {
    public void takeTemperature(){
        System.out.println("測(cè)體溫啦!");
    }

    public void washHand(){
        System.out.println("洗洗手更健康!");
    }
}

xml文件

<?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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.bjwl.*"/>
    <!--目標(biāo)(業(yè)務(wù))對(duì)象-->
    <bean id="student" class="com.bjwl.xmltest.Student"/>
    <bean id="teacher" class="com.bjwl.xmltest.Teacher"/>
    <!--通知(切面)對(duì)象-->
    <bean id="checktor" class="com.bjwl.xmltest.Checktor"></bean>

    <aop:config>
        <!--定義(切面)對(duì)象-->
        <aop:aspect ref="checktor">
            <!--定義切點(diǎn)-->
            <aop:pointcut id="point_test_d" expression="execution(* com.bjwl.xmltest.Student.to*(..))"/>
            <!--定義通知-->
            <aop:before method="takeTemperature" pointcut-ref="point_test_d"></aop:before>
            <aop:after method="washHand" pointcut-ref="point_test_d"></aop:after>
        </aop:aspect>
    </aop:config>
</beans>

其中:目標(biāo)對(duì)象是student對(duì)象,切點(diǎn)是student對(duì)象中方法名前兩個(gè)字母是to的所有方法,事前執(zhí)行測(cè)溫(takeTemperature)、事后執(zhí)行洗手(washHand)
測(cè)試代碼如下:

public class StudentTest {
    @Test
    public void toSchool() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
                "bean02.xml"
        );
        Student student = (Student)applicationContext.getBean("student");
        student.toSchool();
    }
 } 

運(yùn)行結(jié)果如下:

在這里插入圖片描述

如果教師需也需要測(cè)溫,編寫教師類,代碼如下:

public class Teacher {
    public void toSchool(){
        System.out.println("高高興興去上班!");
    }

    public void toEat(){
        System.out.println("教工餐廳去吃飯!");
    }

    public void toClass(){
        System.out.println("排排坐,聽講座!");
    }
}

xml文件更改如下:

    <aop:config>
        <!--定義(切面)對(duì)象-->
        <aop:aspect ref="checktor">
            <!--定義切點(diǎn)-->
            <aop:pointcut id="point_test_d" expression="execution(* com.bjwl.xmltest.*.to*(..))"/>
            <!--定義通知-->
            <aop:before method="takeTemperature" pointcut-ref="point_test_d"></aop:before>
            <aop:after method="washHand" pointcut-ref="point_test_d"></aop:after>
        </aop:aspect>
    </aop:config>

則表示com.bjwl.xmltest中的所有類的對(duì)象均為目標(biāo)對(duì)象,前兩個(gè)字母帶to的方法前后均為切點(diǎn)。

注解方式:
學(xué)生類代碼:

在這里插入圖片描述

切面類的代碼

在這里插入圖片描述

xml文件:

在這里插入圖片描述

運(yùn)行結(jié)果等同,XML文件。

這樣做的好處,學(xué)生類、教師類、切面類具有職責(zé)單一性,提現(xiàn)業(yè)務(wù)邏輯封裝性,動(dòng)態(tài)增強(qiáng)符合開閉原則。

小結(jié)

以上簡單的介紹了面向切面編程的基本概念和基本用法。用好面向切面的編程技術(shù)很不易,因?yàn)榍悬c(diǎn)只能設(shè)置到需要增強(qiáng)功能前面或后面,對(duì)程序設(shè)計(jì)人員要求很高,要求能夠根據(jù)編程經(jīng)驗(yàn)和技巧設(shè)計(jì)出合理的切點(diǎn),需要提現(xiàn)類的層次性。如:執(zhí)行SQL語句前,在控制臺(tái)輸出完整的SQL語句的切點(diǎn),切點(diǎn)就不能設(shè)置到你自己定義的Dao中,而是設(shè)置在PrepareStatement的exectuce的方法前。不過也不用擔(dān)心,使用各種框架時(shí),常用的日志等,已經(jīng)給我們?cè)O(shè)置了開關(guān)變量,我們直接使用即可,非常簡單。

以上就是java開發(fā)AOP面向切面編程入門的詳細(xì)內(nèi)容,更多關(guān)于java面向切面編程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 如何使用Guava Cache做緩存

    如何使用Guava Cache做緩存

    Cache在ConcurrentHashMap的基礎(chǔ)上提供了自動(dòng)加載數(shù)據(jù)、清除數(shù)據(jù)、get-if-absend-compute的功能,本文給大家介紹如何使用Guava Cache做緩存,感興趣的朋友一起看看吧
    2023-11-11
  • 詳解使用Spring快速創(chuàng)建web應(yīng)用的兩種方式

    詳解使用Spring快速創(chuàng)建web應(yīng)用的兩種方式

    這篇文章主要介紹了詳解使用Spring快速創(chuàng)建web應(yīng)用的兩種方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • 使用IDEA配置Tomcat和連接MySQL數(shù)據(jù)庫(JDBC)詳細(xì)步驟

    使用IDEA配置Tomcat和連接MySQL數(shù)據(jù)庫(JDBC)詳細(xì)步驟

    這篇文章主要介紹了使用IDEA配置Tomcat和連接MySQL數(shù)據(jù)庫(JDBC)詳細(xì)步驟,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • java實(shí)現(xiàn)多層級(jí)zip解壓的示例代碼

    java實(shí)現(xiàn)多層級(jí)zip解壓的示例代碼

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)多層級(jí)zip解壓的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考一下
    2024-12-12
  • 簡述Springboot @Async 異步方法

    簡述Springboot @Async 異步方法

    這篇文章主要介紹了Springboot @Async 異步方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2018-05-05
  • Java多線程饑餓與公平介紹及代碼示例

    Java多線程饑餓與公平介紹及代碼示例

    這篇文章主要介紹了Java多線程饑餓與公平介紹及代碼示例,分析饑餓產(chǎn)生的原因以及相關(guān)實(shí)例,然后就在java中實(shí)現(xiàn)公平性問題做了詳細(xì)解析,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • java selenium處理Iframe中的元素示例

    java selenium處理Iframe中的元素示例

    本文主要介紹java selenium處理Iframe中的元素,這里整理了相關(guān)資料并附有示例代碼和實(shí)現(xiàn)方法,有需要的小伙伴可以參考下
    2016-08-08
  • 聊聊Java 中的線程中斷

    聊聊Java 中的線程中斷

    這篇文章主要介紹了Java 中的線程中斷的相關(guān)資料,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-11-11
  • 了解java Struts攔截器的相關(guān)操作

    了解java Struts攔截器的相關(guān)操作

    Struts為我們實(shí)現(xiàn)了很多的功能,比如數(shù)據(jù)自動(dòng)封裝,文件上傳功能阿。Struts為我們提供的這些功能都是通過攔截器完成的。下面我們來詳細(xì)了解一下吧
    2019-06-06
  • java 實(shí)現(xiàn)隨機(jī)數(shù)組輸出及求和實(shí)例詳解

    java 實(shí)現(xiàn)隨機(jī)數(shù)組輸出及求和實(shí)例詳解

    這篇文章主要介紹了java 實(shí)現(xiàn)隨機(jī)數(shù)組輸出及求和實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2016-11-11

最新評(píng)論