4、spring核心AOP
?
Spring AOP
?
1. Spring AOP 概述 1-1
1.1. 何為AOP? 1-1
1.2. AOP要解決什么問題? 1-1
1.3. AOP實際項目應用場景? 1-2
1.4. AOP底層原理實現分析? 1-2
2. Spring AOP 編程實現 2-2
2.1. AOP 基本步驟 2-2
2.2. AOP 基于xml實現 2-2
2.2.1. 創建項目添加依賴 2-3
2.2.2. 添加spring配置文件 2-3
2.2.3. 創建核心業務類 2-4
2.2.4. 創建日志處理類 2-4
2.2.5. 配置bean對象 2-5
2.2.6. 編寫測試類 2-6
3. 總結 3-7
3.1. 重點和難點分析 3-7
3.2. 常見FAQ 3-7
?
1.?Spring AOP 概述
1.1.?何為AOP?
AOP 是軟件設計領域中的面向切面編程,它是面向對象編程的一種補充和完善實際項目中我們通常將面向對象理解為一個靜態過程(例如一個系統有多少模塊,一個模塊有哪些對象,對象有哪些屬性),面向切面理解為一個動態過程(在對象運行時動態織入一些功能。)
?
?
1.2.?AOP要解決什么問題?
實際項目中通常會將系統兩大部分:核心關注點和非核心關注點
思考?
編程過程中首先要完成的是什么?核心關注點(核心業務)
非核心關注點如何切入到系統中?硬編碼(違背OCP),AOP(推薦)
?
AOP就是要在基于OCP在不改變原有系統核心業務代碼的基礎上動態添加一些擴展功能。
?
1.3.?AOP實際項目應用場景?
?
AOP 通常應用于日志的處理,事務處理,權限處理,緩存處理等等。
??
?
1.4.?AOP底層原理實現分析?
? AOP底層基于代理機制實現功能擴展:(了解)
1)?假如目標對象(被代理對象)實現接口,則底層默認采用JDK動態代理機制為目標對象創建代理對象(目標類和代理類會實現共同接口)
2)?假如目標對象(被代理對象)沒有實現接口,則底層默認采用CGLIB代理機制為目標對象創建代理對象(默認創建的代理類會繼承目標對象類型)。
?
2.?Spring AOP 編程實現
? 2.1.?AOP 基本步驟
? step1:創建maven java 項目
step2:添加aop依賴
step3:配置aop 核心(基于xml,基于注解)
step4:定義核心業務(核心關注點):推薦先寫接口再寫實現類
step5:定義擴展業務(非核心關注點)
step6:基于配置實現非核心業務的切入
step7:編寫測試類進行單元測試
?
2.2.?AOP 基于xml實現
? 通過AOP為核心業務類添加日志處理
2.2.1.?創建項目添加依賴
創建maven java 項目然后添加依賴
? 2.2.2.?添加spring配置文件
?
?
2.2.3.?創建核心業務類
創建接口
public interface HelloService {void sayHello(String msg); }
?
創建接口實現類
public class HelloServiceImpl implements HelloService {public void sayHello(String msg) {//假設這條語句是我們系統中的核心業務 System.out.println(msg);} }2.2.4.?創建日志處理類
?
public class LoggingAspect {public void beforeMethod(){System.out.println("method start");}public void afterMethod(){System.out.println("method end");} }?
2.2.5.?配置bean對象
?
<?xml version="1.0" encoding="UTF-8"?> <beans default-lazy-init="true"xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:util="http://www.springframework.org/schema/util"xmlns:jpa="http://www.springframework.org/schema/data/jpa"xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsdhttp://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd"> <!-- 核心業務對象 --><bean id="helloService"class="spring.beans.HelloServiceImpl"/><!-- 配置非核心業務對象(日志處理對象):切面 --><bean id="log" class="spring.aop.LoggingAspect"/><!-- AOP配置(切入點,切面) --> <aop:config><!-- 配置切入點 --><aop:pointcut expression="within(spring.beans.HelloServiceImpl)" id="logPointCut"/><!-- 配置日志處理 --><aop:aspect ref="log" ><aop:before method="beforeMethod" pointcut-ref="logPointCut"/><aop:after method="afterMethod"pointcut-ref="logPointCut"/></aop:aspect></aop:config> </beans>?
2.2.6.?編寫測試類
?
//1.初始化spring容器ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");//2.獲取Bean對象HelloService helloService=ctx.getBean("helloService",HelloService.class);//3.執行業務helloService.sayHello("CGB1710");//proxy的方法//4.釋放資源ctx.close();?
?
2.3.?AOP 基于注解實現
先參考AOP參考文檔進行整理,后續上傳?
1.1.1.?創建maven 項目添加依賴
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>4.3.9.RELEASE</version></dependency><!--Spring AOP的實現依托于Aspect框架所以要引用1.8.5有問題--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.8.9</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.9</version></dependency>?
?
?
?
1.1.2.?創建核心業務類
定義一個訂單接口,此接口中定義多個業務操作。
?
public interface OrderService {public void saveOrder();public void deleteOrder(); }?
1.1.3.?創建時間處理類
將此時間處理類作為核心業務增強(一個橫切面對象)類,用于輸出業務開始執行時間,以及業務結束執行時間。
橫切面對象主要由兩部分構成:切入點(用于@Pointcut標識),以及功能增強(用通知@Before,@After等進行標識)
?
@Aspect @Service public class TimeAspect {@Pointcut("bean(orderService)")public void pointcut(){}/**增強功能:前置通知(業務方法執行之前執行)*/@Before("pointcut()")public void begin(){System.out.println("start:"+System.nanoTime());}/**增強功能:最終通知(業務方法執行最后執行,*無論業務方法是否執行成功,此功能都要執行)*/@After("pointcut()")public void end(){System.out.println("end:"+System.nanoTime());} }?
其中:
@Aspect 注解用于標識此類為一個AOP橫切面對象
@Pointcut 注解用于定義本類中的切入點,本案例中切入點表達式用的是bean表達式,這個表達式以bean開頭,bean括號中的內容為一個spring管理的某個bean對象的id。
@Before 用于定義一個前置通知(滿足切入點表達式的核心業務方法執行之前要執行的一個操作)
@After ?用于定義一個后置通知(滿足切入點表達式的核心業務方法執行之后要執行的一個操作)
?
術語增強:
切面:用于封裝擴展業務的一個類的對象。
通知:切面擴展業務中的一個操作。
?
1.1.4.?配置AOP實現
對于基于注解方式的配置一般有兩種方式,一種是直接在xml核心配置文件中進行配置,還有一種在類中基于注解進行配置。例如
? 基于xml方式配置對注解的應用
?
<?xml version="1.0" encoding="UTF-8"?> <beans default-lazy-init="true"xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:util="http://www.springframework.org/schema/util"xmlns:jpa="http://www.springframework.org/schema/data/jpa"xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsdhttp://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd"> <!-- 配置對類組件的掃描 --><context:component-scan base-package="com.spring"/><!-- 啟用AOP注解(自動為目標對象創建代理對象) --><aop:aspectj-autoproxy/></beans>?
?
在類中基于注解方式的配置
?
@ComponentScan("com.spring.beans") @EnableAspectJAutoProxy public class AppConfig {}?
1.1.5.?編寫測試類
?
public class TestAOP01 {public static void main(String[] args) {//1.初始化容器ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");//2.獲取bean對象OrderService os=(OrderService)ctx.getBean("orderService", OrderService.class);//3.執行業務方法 os.saveOrder();os.deleteOrder();//4.釋放資源 ctx.close();} }?
基于類中注解方式配置的測試實現
?
public class TestAOP02 {public static void main(String[] args) {//1.初始化容器對象AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext(AppConfig.class);//2.獲取Bean對象OrderService orderService=ctx.getBean("orderService", OrderService.class);//3.執行業務 orderService.saveOrder();//orderService.deleteOrder();//4.釋放資源 ctx.close();} }?
?
基于類的注解配置,初始化工廠時需要初始化
AnnotationConfigApplicationContext對象。
?
2.?Spring AOP 編程增強
2.1.?切面表達式增強
?
Spring中通過切入點表達式定義具體切入點,其常用AOP切入點表達式定義及說明:
?
| ? | 指示符 | 作用 |
| ? | bean | 用于匹配指定bean id的的方法執行 |
| ? | within | 用于匹配指定包名下類型內的方法執行 |
| ? | execution | 用于進行細粒度方法匹配執行具體業務 |
?
2.1.1.?Bean表達式應用增強
? bean應用于類級別,實現粗粒度的控制:
?
| bean(UserServiceImpl)) | 指定一個類 |
| bean(*Service) | 指定所有的后綴為service的類 |
?
?
2.1.2.?Within表達式應用增強
? within應用于類級別,實現粗粒度的控制:
| within(aop.service.UserServiceImpl)) | 指定類,只能指定一個類 |
| within(aop.service.*)) | 只包括當前目錄下的類 |
| within(aop.service..*)) | 指定當前目錄包含所有子目錄中的類 |
?
?
2.1.3.?Execution表達式應用增強
execution方法級別,細粒度的控制:
語法:execution(返回值類型 包名.類名.方法名(參數列表))
| execution(void aop.service.UserServiceImpl.addUser()) | 匹配方法 |
| execution(void aop.service.PersonServiceImpl.addUser(String)) | 方法參數必須為字符串 |
| execution(* aop.service..*.*(..)) | 萬能配置 |
?
?
? 2.2.?切面通知增強
在AOP編程中有五種類型的通知:
1)?前置通知
2)?后置通知
3)?異常通知
4)?最終通知
5)?環繞通知
?
2.2.1.?Xml方式通知配置增強
切入點及前置通知,后置通知,返回通知,異常通知,環繞通知的配置
?
<aop:config><aop:pointcut id="pc"expression="execution(* com.company.spring.service..*.*(..))" ><aop:aspect ref="loggingAspect"><aop:before method="beforeMethod" pointcut-ref="pc"/><aop:after method="afterMethod" pointcut-ref="pc"/><aop:after-returning method="returnMethod"pointcut-ref="pc"/><aop:after-throwing method="throwMethod" pointcut-ref="pc"/></aop:aspect></aop:config>切入點及環繞通知的配置(了解)<aop:config><aop:pointcut id="pc"expression="execution(* com.company.spring.service..*.*(..))" ><aop:aspect ref="loggingAspect"><aop:around method="aroundMethod" pointcut-ref="pc"/></aop:aspect></aop:config>
?
2.2.2.?注解方式通知配置增強
切入點及前置通知,后置通知,返回通知,異常通知,環繞通知的配置
?
@Aspect @Service public class TxAspect {@Before("bean(orderService)")public void startTx(){System.out.println("開啟事務");}@AfterReturning("bean(orderService)")public void commitTx(){System.out.println("提交事務");}@AfterThrowing("bean(orderService)")public void rollbackTx(){System.out.println("回滾事務");}@After("bean(orderService)")public void closeResource(){System.out.println("釋放資源");} }?
?
切入點及環繞通知的配置
?
@Component @Aspect public class TxManager {@Pointcut("execution(com.company.spring.service..*.*(..))")public void pointCut() {}@Around("pointCut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("事務開始");Object result = joinPoint.proceed();System.out.println("事務結束");return result;} }?
2.3.?切面執行順序配置增強
實際項目中可能會有多個切面,切面之間的執行可能需要一定的順序
2.3.1.?Xml方式配置執行順序
?
<aop:config><aop:pointcut id="pc"expression="execution(* com.company.spring.service..*.*(..))"/><aop:aspect ref="loggingAspect" order="1"><aop:around method="aroundMethod" pointcut-ref="pc"/></aop:aspect><aop:aspect ref="txManager" order="2"><aop:around method="aroundMethod" pointcut-ref="pc"/></aop:aspect></aop:config>?
2.3.2.?注解方式配置執行順序
注解方式順序配置需要借助@Order注解
?
@Order(1) @Aspect @Component public class TxManager {@Pointcut("execution(* com.company.spring.service..*.(..))")public void pointCut() {}@Around("pointCut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("事務開始");Object result = joinPoint.proceed();System.out.println("事務結束");return result;} }?
注解方式順序配置
@Order(2) @Aspect @Component public class LoggingAspect {@Pointcut("execution(* com.company.spring.service..*.(..))")public void pointCut() {}@Before("pointCut()")public void beforeMethod() {System.out.println("beforeMethod");}@Before("pointCut()")public void afterMethod() {System.out.println("afterMethod");} }?
3.?總結
3.1.?重點和難點分析
?
3.2.?常見FAQ
?
| 3.3.?作業 ? |
轉載于:https://www.cnblogs.com/xiangyuqi/p/8655444.html
總結
以上是生活随笔為你收集整理的4、spring核心AOP的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Conputer Vision-边缘检测
- 下一篇: Spring Boot中使用AOP统一处