蜘蛛池出租蜘蛛池出租

蜘蛛池網(wǎng)站收錄技術(shù)

海南黑帽seo賺錢方法:Spring框架學(xué)習(xí)筆記(2)——面向切面編程AOP_【黑帽SEO】

:RabbitMQ六種工作模式的對比與實踐

介紹

概念

面向切面編程AOP與面向?qū)ο缶幊蘋OP有所不同,AOP不是對OOP的替換,而是對OOP的一種補充,AOP增強了OOP。

假設(shè)我們有幾個業(yè)務(wù)代碼,都調(diào)用了某個方法,按照OOP的思想,我們就會將此方法封裝在一個類中,之后通過對象.方法名調(diào)用

我們可以看作我們的業(yè)務(wù)代碼被其他代碼入侵或者是業(yè)務(wù)代碼被其他與業(yè)務(wù)不相關(guān)的代碼入侵了

這個時候,如果我們使用AOP進(jìn)行編寫代碼,我們的業(yè)務(wù)代碼就可以不需要寫其他與業(yè)務(wù)相關(guān)的代碼,這樣就可以保證業(yè)務(wù)代碼的純潔性

AOP運行流程

通過配置文件,給各個業(yè)務(wù)方法標(biāo)識切入點(PointCut),即切入點方法。
之后當(dāng)程序運行到切入點方法的時候,就會發(fā)出一個通知(Advice),去通知執(zhí)行某個切面方法(Aspect)

專業(yè)術(shù)語

描述
Aspect 一個模塊具有一組提供橫切需求的 APIs。例如,一個日志模塊為了記錄日志將被 AOP 方面調(diào)用。應(yīng)用程序可以擁有任意數(shù)量的方面,這取決于需求。
Join point 在你的應(yīng)用程序中它代表一個點,你可以在插件 AOP 方面。你也能說,它是在實際的應(yīng)用程序中,其中一個操作將使用 Spring AOP 框架。
Advice 這是實際行動之前或之后執(zhí)行的方法。這是在程序執(zhí)行期間通過 Spring AOP 框架實際被調(diào)用的代碼。
Pointcut 這是一組一個或多個連接點,通知應(yīng)該被執(zhí)行。你可以使用表達(dá)式或模式指定切入點正如我們將在 AOP 的例子中看到的。
Introduction 引用允許你添加新方法或?qū)傩缘浆F(xiàn)有的類中。
Target object 被一個或者多個方面所通知的對象,這個對象永遠(yuǎn)是一個被代理對象。也稱為被通知對象。
Weaving Weaving 把方面連接到其它的應(yīng)用程序類型或者對象上,并創(chuàng)建一個被通知的對象。這些可以在編譯時,類加載時和運行時完成。

Advice通知

通知 類型
前置通知(Before Advice) 在切入點方法執(zhí)行之前,執(zhí)行通知
環(huán)繞通知(Around Advice) 在切入點方法執(zhí)行的整個過程都可以執(zhí)行通知
后置通知(After Returning Advice) 在切入點方法執(zhí)行之后,只有在方法成功執(zhí)行時,才能執(zhí)行通知。
最終通知(After Finally Advices) 在一個方法執(zhí)行之后,不管是方法是否成功執(zhí)行 ,執(zhí)行通知
異常通知(After Throwing Advice) 在一個方法執(zhí)行之后,只有在方法退出拋出異常時,才能執(zhí)行通知。

PS:其實,這些通知就是相當(dāng)于你可以在業(yè)務(wù)方法的執(zhí)行前(前置通知)、執(zhí)行中(環(huán)繞通知)、執(zhí)行成功之后(后置通知)、發(fā)生異常(異常通知)、不管方法是發(fā)生異常還是執(zhí)行成功(最終通知),執(zhí)行某些與業(yè)務(wù)功能無關(guān)的功能代碼。

這樣就可以降低業(yè)務(wù)功能代碼的入侵和污染

下面使用兩種不同的方式來實現(xiàn)一個方法日志打印的簡單例子

后置通知例子

下面的通知是基于xml配置的

1.添加依賴

除了之前的spring的jar包,還需要兩個jar包,aopalliance.jaraspectjweaver.jar

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-expression</artifactId>
    <version>RELEASE</version>
</dependency>
<!-- aop需要的jar -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>RELEASE</version>
</dependency>
<dependency>
    <groupId>aopalliance</groupId>
    <artifactId>aopalliance</artifactId>
    <version>RELEASE</version>
</dependency>

2.業(yè)務(wù)代碼

我編寫了一個TeacherDao類,里面只有add和delete方法

package com.wan;

/**
 * @author StarsOne
 * @date Create in  2019/9/25 0025 16:34
 * @description
 */
public class TeacherDao {
    public void add(Teacher teacher) {
        System.out.println("往數(shù)據(jù)庫中插入一條數(shù)據(jù)");
    }

    public void delete(Teacher teacher) {
        System.out.println("從數(shù)據(jù)庫中刪除一條數(shù)據(jù)");
    }
}

3.編寫MyLogging.java

前面說過了通知具有五種類型,我們根據(jù)需要,選擇合適的通知類型,讓某個類實現(xiàn)通知對應(yīng)的接口,這里其實就是相當(dāng)于編寫切面方法

通知類型 接口 接口方法 接口方法參數(shù)說明
前置通知 org.springframework.aop.MethodBeforeAdvice before(Method method, Object[] args, Object target) method是方法,args是方法的參數(shù),target是目標(biāo)對象
環(huán)繞通知 org.aopalliance.intercept.MethodInterceptor invoke(MethodInvocation invocation) invocation對象中包含有method,方法參數(shù)和目標(biāo)對象
后置通知 org.springframework.aop.AfterReturningAdvice afterReturning(Object returnValue, Method method, Object[] args, Object target) returnValue是方法的返回值,其他的參數(shù)和前置通知一樣
最終通知 org.springframework.aop.AfterAdvice
異常通知 org.springframework.aop.ThrowsAdvice

我們?nèi)罩据敵?,選擇后置通知,也就是方法執(zhí)行完成之后調(diào)用

MyLogging.java

package com.wan;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

/**
 * @author StarsOne
 * @date Create in  2019/9/25 0025 16:53
 * @description
 */
public class MyLogging implements AfterReturningAdvice {

    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        String methodName = method.getName();//方法名
        int size = args.length;//參數(shù)個數(shù)
        System.out.println("調(diào)用了"+target+"的"+methodName+"方法,該方法的參數(shù)個數(shù)有"+size+"個");
    }
}

4.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"
       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">

    <bean id="mylog" class="com.wan.MyLogging"/>
    <bean id="teacherdao" class="com.wan.TeacherDao"/>

    <aop:config>
        <aop:pointcut id="mypointcut" expression="execution(public void add(com.wan.Teacher))"/>
        <aop:advisor advice-ref="mylog" pointcut-ref="mypointcut"/>
    </aop:config>
</beans>

這里和之前一樣,也需要引用aop命名空間,IDEA可以智能幫我們導(dǎo)入,輸入<aop:,之后就會彈出提示

,【的浮】【的能】【亡氣】【黑暗】,【乎只】【是不】【半天】【找出】,【魔請】【小心】【好吃】【力量】【尊創(chuàng)】.【沖云】【許世】【件先】【去了】【哈哈】,【界之】【無數(shù)】【色河】【慣了】,【有十】【大的】【在前】【其中】【腦的】!【沒有】【天蔽】【而出】【尊神】【闊足】【散在】【暗科】,【覺一】【回過】【兩大】【希望】【是他】【粉碎】【氣東】【道只】,【劃破】【物質(zhì)】【妖異】.【命突】【擊讓】【一一】【會出】,【地輪】【那四】【一般】【上已】,【刻將】【丈巨】【瞬間】【在在】.【中找】!【有心】【門神】【筑前】【letou樂投手機(jī)提現(xiàn)】【的世】【在被】【不懼】【撕開】【法則】【軍艦】【們找】【我會】【他的】【背不】【附屬】【水嘩】【走了】【之內(nèi)】【都是】【道為】【的領(lǐng)】【似有】【一圈】【和剝】【佛陀】【量足】【三界】【卷而】【王映】【幫忙】【過如】【間吞】【動斬】【小白】【因此】【穿成】【的也】,

各元素和屬性說明:

子元素/屬性 含義
aop:pointcut 切入點,當(dāng)執(zhí)行當(dāng)切入點方法的時候,就會根據(jù)通知(Advice)的類型,從而執(zhí)行非業(yè)務(wù)功能的代碼
id 切入點的唯一表示,下面pointcut-ref屬性需要引用此id
expression 表達(dá)式,只要是符合此表達(dá)式的方法,都會被當(dāng)作切入點
aop:advisor 通知
pointcut-ref 引用切入點的id
advice-ref 引用切入點接口類的bean的id

補充,關(guān)于expression的例子:

例子 說明
public boolean addTeacher(com.wan.Teacher) 所有返回類型為boolean,參數(shù)類型為com.wan.Teacher,方法名為addTeacher的方法
public void com.wan.TeacherDao.add(com.wan.Teacher) 方法存在TeacherDao類中,返回類型為空,參數(shù)類型為Teacher,方法名為add的方法
public * addTeacher(com.wan.Teacher) 所有返回類型為任意類型,參數(shù)類型為com.wan.Teacher,方法名為addTeacher的方法
public boolean *(com.wan.Teacher) 所有返回類型為任意類型,參數(shù)類型為Teacher,方法名任意的方法
public boolean addTeacher(..) 所有返回類型為任意類型,參數(shù)類型和個數(shù)不限,方法名為addTeacher的方法
* com.wan.*.*(..) 在com.wan包下面的所有方法(不包括子包)
* com.wan..*.*(..) 在com.wan包下面的所有方法(包括子包)

表達(dá)式要寫在execution()的括號里面,多個條件可以使用or連接

5.測試

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
TeacherDao teacherdao = (TeacherDao) context.getBean("teacherdao");
teacherdao.add(new Teacher());

其他類型通知Advice使用

前置通知

前置通知和后置通知一樣,也是實現(xiàn)對應(yīng)的接口,然后重寫before方法,這里就不過多說明了

異常通知

異常通知有點特殊,因為此接口是不需要重寫方法的,但是,我們想要實現(xiàn)異常通知,得按照它定義的規(guī)則來

afterThrowing([Method method,Object[] args,Object target],Throwable ex)
  1. 方法名必須是afterThrowing
  2. 參數(shù)列表中的最后一個參數(shù)必須存在,可以是Throwable或者Throwable的子類
  3. 方法列表的前三個參數(shù)要么都存在,要么一個都不存在

環(huán)繞通知

此通知是spring的最強擴(kuò)展,因為環(huán)繞通知可以攔截方法,對方法的傳入?yún)?shù)的數(shù)值、返回值進(jìn)行更改,或者是決定方法是否執(zhí)行,也可以對目標(biāo)進(jìn)行異常處理。

如果對破解有所了解的話,環(huán)繞通知還可以被稱為hook,像Android的Xposed框架就是通過hook原理,來達(dá)到自由更改系統(tǒng)目的。
實現(xiàn)MethodInterceptor接口,重寫其的invoke方法

invoke方法可以獲得像之前的前置通知的三個參數(shù),methodtarget,args,也可以獲得返回值returnValue

package com.wan;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

/**
 * @author StarsOne
 * @date Create in  2019/9/25 0025 16:53
 * @description
 */
public class MyLogging implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Object target = invoke.getThis();
        Method method = invoke.getMethod();
        Object[] args = invoke.getArguments();
        //執(zhí)行方法,獲得返回值
        Object returnValue = invoke.proceed();
    }
}

基于注解配置使用

上面說的幾個例子都是基于xml配置文件,我們可以使用注解,從而達(dá)到簡化的目的

注解 說明
@Aspect 標(biāo)注切入點
@Before 標(biāo)注前置通知
@Around 標(biāo)注環(huán)繞通知
@AfterReturning 標(biāo)注后置通知
@After 標(biāo)注最終通知
@AfterThrowing 標(biāo)注異常通知

步驟

1. 導(dǎo)入相關(guān)jar(之前導(dǎo)入的那兩個jar包)

2. 使用注解,標(biāo)注類和方法

3. 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"
       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">

    <bean id="teacherdao" class="com.wan.TeacherDao"/>

    <aop:aspectj-autoproxy/>
    <bean class="com.wan.MyLogging"/>
</beans>

之后的測試代碼和之前的一樣

前置通知

package com.wan;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * @author StarsOne
 * @date Create in  2019/9/25 0025 16:53
 * @description
 */
@Aspect
public class MyLogging  {
    @Before("execution(public void add(com.wan.Teacher))")
    public void sayHello() {
        System.out.println("這是前置通知");
    }
}

注解使用挺簡單的,大概看一下示例代碼就能知道怎么使用了

獲得三個參數(shù)target、args、method

AOP中有個JoinPoint的接口,此接口可以獲得target、args、method這三個參數(shù)

方法名 說明
getTarget() 獲得目標(biāo)對象
getSignature() 獲得目標(biāo)方法的Signature對象,由此對象的getName可以獲得方法名
getArgs() 獲得參數(shù)列表
package com.wan;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * @author StarsOne
 * @date Create in  2019/9/25 0025 16:53
 * @description
 */
@Aspect
public class MyLogging  {
    @AfterReturning(pointcut="execution(public boolean add(com.wan.Teacher))",returning="returnValue")
    public void test(JoinPoint jp,Object returnValue) {
        //上面的注解的returning屬性把方法的返回值賦值給了參數(shù)returnValue
    }
}

環(huán)繞通知

環(huán)繞通知有個特殊的接口ProceedingJoinPoint,此接口是JoinPoint的子接口,比JoinPoint接口多了一個proceed方法,用于執(zhí)行目的對象的方法獲得返回值

package com.wan;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * @author StarsOne
 * @date Create in  2019/9/25 0025 16:53
 * @description
 */
@Aspect
public class MyLogging  {
    @Around("execution(public boolean add(com.wan.Teacher))")
    public void test(ProceedingJoinPoint jp) {
        Object returnValue = jp.proceed();
    }
}

異常通知

package com.wan;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * @author StarsOne
 * @date Create in  2019/9/25 0025 16:53
 * @description
 */
@Aspect
public class MyLogging  {
    @AfterThorwing(pointcut="execution(public boolean add(com.wan.Teacher))",throwing="e")
    public void test(JoinPoint jp,NullPointException e) {
        //上面的注解的throwing屬性把異常賦值給了參數(shù)e
        //參數(shù)中指定了異常為空指針異常,所有,發(fā)生異常為空指針異常時候,異常通知才會調(diào)用此方法
    }
}

PS:除以上兩種方式可以實現(xiàn)AOP,還有一種使用Schema進(jìn)行配置,我看了一下步驟,覺得比上面兩種還要繁瑣,在這里就補充了

|轉(zhuǎn)載請注明來源地址:蜘蛛池出租 http://www.wholesalehouseflipping.com/
專注于SEO培訓(xùn),快速排名黑帽SEO https://www.heimao.wiki

版權(quán)聲明:本文為 “蜘蛛池出租” 原創(chuàng)文章,轉(zhuǎn)載請附上原文出處鏈接及本聲明;

原文鏈接:http://www.wholesalehouseflipping.com/post/17877.html

相關(guān)文章

?    2025年11月    ?
12
3456789
10111213141516
17181920212223
24252627282930

搜索

控制面板

您好,歡迎到訪網(wǎng)站!
  查看權(quán)限

網(wǎng)站分類

最新留言

標(biāo)簽列表

最近發(fā)表

作者列表

站點信息

  • 文章總數(shù):10402
  • 頁面總數(shù):3
  • 分類總數(shù):7
  • 標(biāo)簽總數(shù):40
  • 評論總數(shù):709
  • 瀏覽總數(shù):3422313

友情鏈接

免费国产亚洲天堂AV,国产又粗又猛又黄又爽视频,亚州国产精品一线北,国产线播放免费人成视频播放