超詳細的Java知識點路線圖
概述
本文介紹Spring架構的另一個重要特性:AOP
1、AOP簡介
1.1 AOP基本概念
AOP(Aspect Oriented Programming)面向切面程式設計,是OOP的一種重要補充,也是Spring的另一個核心。
OOP是基于封裝、繼承、多态的程式設計思想,關注類之間縱向關系;AOP關注橫向關系,能夠為多個互相沒有關系,又都需要某些共同功能的類,提供一些通用服務(如:日志、權限、緩存、事務等)。
1.2 AOP的作用
代碼解耦,可以把與類的核心業務無關,又都需要的功能封裝起來,讓類隻關注自己的核心業務,分離了系統的核心業務和非核心業務。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiIXZ05WZj91YpB3IwczX0xiRGZkRGZ0Xy9GbvNGL2EzXlpXazxSPRRVT41EROpXTU10dVNDTwYVbiVHNHpleO1GTulzRilWO5xkNNh0YwIFSh9Fd4VGdsATMfd3bkFGazxyaHRGcWdUYuVzVa9GczoVdG1mWfVGc5RHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5SNwETNxETM1EjMxAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
1.3 AOP的術語
1、切面(Aspect)
對哪些方法進行攔截,攔截後怎麼處理,這些關注點稱之為切面
2、連接配接點(joinpoint)
被攔截到的點,因為Spring隻支援方法類型的連接配接點,是以在Spring中連接配接點指的就是被攔截到的方法,實際上連接配接點還可以是字段或者構造器
3、切入點(pointcut)
對連接配接點進行攔截的定義
4、通知(advice)
所謂通知指的就是指攔截到連接配接點之後要執行的代碼,通知分為前置、後置、異常、最終、環繞通知五類
5、目标對象(target)
代理的目标對象,将切面應用到目标對象并導緻代理對象建立的過程
6、引入\織入(introduction、weave)
在不修改代碼的前提下,引入可以在運作期為類動态地添加一些方法或字段
# 2、AOP的實作
2.1 AOP配置步驟
2.1.1 引入依賴
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
2.1.2 編寫通知類
/**
* 日志輸出通知類
*/
public class LogAdvise {
public void beforeLog(){
System.out.println("方法開始執行!");
}
public void afterLog(){
System.out.println("方法後置執行!");
}
public void afterReturning(){
System.out.println("方法傳回了資料");
}
public void afterThrowing(){
System.out.println("方法抛出了異常");
}
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("around方法名:" + joinPoint.getSignature().getName());
System.out.println("around --前置");
//原來方法
joinPoint.proceed();
System.out.println("around --後置");
}
}
2.1.3 AOP的配置
<?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:context="http://www.springframework.org/schema/context"
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/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--配置包的掃描-->
<context:component-scan base-package="com.blb.aop_demo"></context:component-scan>
<!--配置通知類-->
<bean id="logAdvise" class="com.blb.aop_demo.util.LogAdvise"></bean>
<!--配置切面-->
<aop:config>
<!--配置切入點-->
<aop:pointcut id="pc" expression="execution(* com.blb.aop_demo.service.*Service.*(..))"/>
<!--配置切面 ref是通知類的bean-->
<aop:aspect id="aspect1" ref="logAdvise">
<!--前置通知 method是對應的通知方法 pointcut-ref是切入點-->
<aop:before method="beforeLog" pointcut-ref="pc"></aop:before>
<!--後置-->
<aop:after method="afterLog" pointcut-ref="pc"></aop:after>
<!--後置傳回-->
<aop:after-returning method="afterReturning" pointcut-ref="pc"></aop:after-returning>
<!--後置抛異常-->
<aop:after-throwing method="afterThrowing" pointcut-ref="pc"></aop:after-throwing>
<!--環繞-->
<aop:around method="around" pointcut-ref="pc"></aop:around>
</aop:aspect>
</aop:config>
</beans>
2.1.4 測試
在com.blb.aop_demo.service包下添加幾個Service類做測試,可以看到執行的方法加入了前置、後置、環繞等功能
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-aop.xml");
GoodsService goodsService = context.getBean(GoodsService.class);
goodsService.queryGoods();
goodsService.queryGoodsById(1);
goodsService.createGoods();
goodsService.updateGoods();
goodsService.deleteGoodsById(1);
2.1.5 配置詳解
aop:pointcut 是切入點配置
其中的核心是expression,通過表達式控制切面應用的範圍
文法:
execution(通路修飾符 傳回值 包名.類名.方法名(參數類型,參數類型....))
通配符:
*代表任意長度的字元
.. 代替子包或任意參數
3、AOP的注解配置
3.1 常用AOP相關注解
@Aspect 切面,配置到切面類上
@PointCut(“表達式”) 配置切入點,加在方法上
@Before 配置前置通知方法
@After 配置後置通知方法
@Around 配置環繞通知方法
@AfterReturning 配置後置傳回值通知方法
@AfterThrowing 配置後置抛出異常通知方法
3.2 AOP配置
1)配置類
@ComponentScan(basePackages = "com.blb.aop_demo")
@Configuration
//啟動AspectJ的注解配置
@EnableAspectJAutoProxy
public class AopConfig {
}
2) 日志切面
/**
* 日志切面
*/
@Aspect
@Component
public class LogAspect {
//配置切入點
@Pointcut("execution(* com.blb.aop_demo.service.*Service.*(..))")
public void pointcut(){
}
//配置通知方法
@Before("pointcut()")
public void beforeLog(){
System.out.println("這是前置的通知方法!!");
}
}
3)測試
AnnotationConfigApplicationContext context2 = new
AnnotationConfigApplicationContext(AopConfig.class);
GoodsService goodsService = context2.getBean(GoodsService.class);
goodsService.queryGoods();
goodsService.queryGoodsById(1);
goodsService.createGoods();
goodsService.updateGoods();
goodsService.deleteGoodsById(1);
4、日志跟蹤案例
4.1 案例概述
在實際項目部署上線後,都需要通過日志的搜集來定位出現的bug,日志跟蹤代碼如果在所有方法都寫,就會很繁瑣,代碼也不利于維護,如果使用AOP就能很好解決這個問題。
4.2 案例實作
- 導入log4j依賴
- 添加log4j.properties
- 編寫日志切面
/**
* Log4j日志輸出切面
*/
@Aspect
@Component
public class Log4jAspect {
//建立日志對象
private Logger logger = Logger.getLogger(Log4jAspect.class);
//給所有的service類的所有方法加日志跟蹤
@Pointcut("execution(* com.blb.aop_demo.service.*Service.*(..))")
public void logPointcut(){
}
//配置環繞通知
@Around("logPointcut()")
public Object aroundLog(ProceedingJoinPoint point) throws Throwable {
//記錄方法執行前時間
long start = System.currentTimeMillis();
//列印方法名稱
if(logger.isDebugEnabled()){
logger.debug("目前執行方法:" + point.getSignature().getName());
}
//列印參數
Object[] args = point.getArgs();
for(Object arg : args){
if(logger.isDebugEnabled()){
logger.debug("參數:"+arg);
}
}
//列印傳回值
Object result = point.proceed();
if(logger.isDebugEnabled()){
logger.debug("方法傳回值:" +result);
}
//列印執行時間
long end = System.currentTimeMillis();
if(logger.isDebugEnabled()){
logger.debug("方法執行時間:" +(end - start));
}
return result;
}
}
結束
大家如果需要學習其他Java知識點,戳這裡 超詳細的Java知識點彙總