蜘蛛池出租蜘蛛池出租

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

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

:RabbitMQ六種工作模式的對(duì)比與實(shí)踐

介紹

概念

面向切面編程AOP與面向?qū)ο缶幊蘋(píng)OP有所不同,AOP不是對(duì)OOP的替換,而是對(duì)OOP的一種補(bǔ)充,AOP增強(qiáng)了OOP。

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

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

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

AOP運(yùn)行流程

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

專(zhuān)業(yè)術(shù)語(yǔ)

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

Advice通知

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

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

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

下面使用兩種不同的方式來(lái)實(shí)現(xiàn)一個(gè)方法日志打印的簡(jiǎn)單例子

后置通知例子

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

1.添加依賴(lài)

除了之前的spring的jar包,還需要兩個(gè)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ù)代碼

我編寫(xiě)了一個(gè)TeacherDao類(lèi),里面只有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ù)庫(kù)中插入一條數(shù)據(jù)");
    }

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

3.編寫(xiě)MyLogging.java

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

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

我們?nèi)罩据敵觯x擇后置通知,也就是方法執(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ù)個(gè)數(shù)
        System.out.println("調(diào)用了"+target+"的"+methodName+"方法,該方法的參數(shù)個(gè)數(shù)有"+size+"個(gè)");
    }
}

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:,之后就會(huì)彈出提示

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

各元素和屬性說(shuō)明:

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

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

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

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

5.測(cè)試

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

其他類(lèi)型通知Advice使用

前置通知

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

異常通知

異常通知有點(diǎn)特殊,因?yàn)榇私涌谑遣恍枰貙?xiě)方法的,但是,我們想要實(shí)現(xiàn)異常通知,得按照它定義的規(guī)則來(lái)

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

環(huán)繞通知

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

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

invoke方法可以獲得像之前的前置通知的三個(gè)參數(shù),method,targetargs,也可以獲得返回值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();
    }
}

基于注解配置使用

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

注解 說(shuō)明
@Aspect 標(biāo)注切入點(diǎn)
@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)入的那兩個(gè)jar包)

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

3. xml中開(kāi)啟配置

<?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>

之后的測(cè)試代碼和之前的一樣

前置通知

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("這是前置通知");
    }
}

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

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

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

方法名 說(shuō)明
getTarget() 獲得目標(biāo)對(duì)象
getSignature() 獲得目標(biāo)方法的Signature對(duì)象,由此對(duì)象的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)繞通知有個(gè)特殊的接口ProceedingJoinPoint,此接口是JoinPoint的子接口,比JoinPoint接口多了一個(gè)proceed方法,用于執(zhí)行目的對(duì)象的方法獲得返回值

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ā)生異常為空指針異常時(shí)候,異常通知才會(huì)調(diào)用此方法
    }
}

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

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

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

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

相關(guān)文章

?    2025年12月    ?
1234567
891011121314
15161718192021
22232425262728
293031

搜索

控制面板

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

網(wǎng)站分類(lèi)

最新留言

標(biāo)簽列表

最近發(fā)表

作者列表

站點(diǎn)信息

  • 文章總數(shù):10735
  • 頁(yè)面總數(shù):3
  • 分類(lèi)總數(shù):7
  • 標(biāo)簽總數(shù):40
  • 評(píng)論總數(shù):804
  • 瀏覽總數(shù):3684674

友情鏈接

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