AOP面向切面編程
什么是AOP
AOP (Aspect Oriented Programming)意為:面向切面編程,通過預編譯方式和運行期動態代理實作程式功能的統一維護的一種技術,AOP是OOP的延續,是軟體開發中的一個熱點,也是Spring框架中的一個重要內容,是函式式編程的一種衍生范型,利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率,
OOP (Object Oriented Programming) 面向物件編程
AOP (Aspect Oritented Programming) 面向切面編程
OOP 到AOP 不是替換的關系,而是一種擴展,使用了AOP后,OOP還是會繼續使用
Aop在Spring中的作用
提供宣告式事務;允許用戶自定義切面
- 橫切關注點:跨越應用程式多個模塊的方法或功能,即是,與我們業務邏輯無關的,但是我們需要關注的部分,就是橫切關注點,如日志,安全,快取,事務等等.....
- 切面(ASPECT)︰橫切關注點被模塊化的特殊物件,即,它是一個類,
- 通知(Advice) :切面必須要完成的作業,即,它是類中的一個方法,·
- 目標(Target):被通知物件,
- 代理(Proxy) ︰向目標物件應用通知之后創建的物件,
- 切入點(PointCut) :切面通知執行的“地點""的定義,
- 連接點(JointPoint) : 與切入點匹配的執行點,
AOP 主要就是在不改變原本代碼的前提下,新增功能上去不影響原本的功能,
AOP在Spring中是非常重要的一個功能,可以理解為一個業務就是一條線,當使用一把刀在這條線的指定位置砍下去,添加新的功能到斷開處,最后在進行織入,最后連起來成為了一條新的線,新的功能就可以實作,
使用Spring實作Aop
添加依賴
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.18</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.6</version>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.18</version>
</dependency>
注解實作
修改組態檔
<?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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xs">
<!--注解掃描 默認開啟注解支持-->
<context:component-scan base-package="com.bing"/>
<!--
proxy-target- 如果是true 就是cglib代理 如果是false就是jdk 默認是false
-->
<aop:aspectj-autoproxy />
</beans>
添加一個切面類
package com.bing.aspect;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* @Author IBing
* @Date 2022/8/26 22:01
* @Version 1.0
*/
@Aspect //表示這是一個 切面類
@Component //將物件放入spring容器
public class UserAspect {
//開啟日志
private Logger logger = Logger.getLogger(UserAspect.class);
/**
* 目標方法執行之前執行
* @param joinPoint
*/
@Before("execution(public com.bing.entity.User com.bing.service.impl.UserServiceImpl.login(java.lang.String,java.lang.String))")
public void before(JoinPoint joinPoint){
logger.debug("before");
logger.debug("攔截的目標物件"+joinPoint.getTarget());
logger.debug("攔截的方法"+joinPoint.getSignature().getDeclaringTypeName()+joinPoint.getSignature().getName());
logger.debug("攔截的引數"+joinPoint.getArgs());
logger.debug("攔截的位置"+joinPoint.getStaticPart());
logger.debug("攔截的代理物件"+joinPoint.getStaticPart());
}
/**
* 無論是否拋出例外都會執行,相當于finally
* @param joinPoint
*/
@After("execution(public com.bing.entity.User com.bing.service.impl.UserServiceImpl.login(java.lang.String,java.lang.String))")
public void after(JoinPoint joinPoint){
logger.debug("after");
logger.debug("攔截的目標物件"+joinPoint.getTarget());
logger.debug("攔截的方法"+joinPoint.getSignature().getDeclaringTypeName()+joinPoint.getSignature().getName());
logger.debug("攔截的引數"+joinPoint.getArgs());
logger.debug("攔截的位置"+joinPoint.getStaticPart());
logger.debug("攔截的代理物件"+joinPoint.getStaticPart());
}
/**
* 相當于try
* @param joinPoint
*/
@AfterReturning("execution(public com.bing.entity.User com.bing.service.impl.UserServiceImpl.login(java.lang.String,java.lang.String))")
public void afterReturning(JoinPoint joinPoint){
logger.debug("afterReturning");
logger.debug("攔截的目標物件"+joinPoint.getTarget());
logger.debug("攔截的方法"+joinPoint.getSignature().getDeclaringTypeName()+joinPoint.getSignature().getName());
logger.debug("攔截的引數"+joinPoint.getArgs());
logger.debug("攔截的位置"+joinPoint.getStaticPart());
logger.debug("攔截的代理物件"+joinPoint.getStaticPart());
}
/**
* 相當于catch
* @param joinPoint
* @param e
*/
@AfterThrowing(value="https://www.cnblogs.com/bingshen/archive/2022/08/26/execution(public com.bing.entity.User com.bing.service.impl.UserServiceImpl.login(java.lang.String,java.lang.String))",throwing ="e" )
public void afterThrowing(JoinPoint joinPoint,RuntimeException e){
logger.debug("afterThrowing");
logger.debug("攔截的目標物件"+joinPoint.getTarget());
logger.debug("拋出的例外為",e);
}
/**
* 環繞執行
* @param pjd
* @return
* @throws Throwable
*/
@Around("execution(public com.bing.entity.User com.bing.service.impl.UserServiceImpl.login(java.lang.String,java.lang.String))")
public Object around(ProceedingJoinPoint pjd) throws Throwable {
logger.debug("around之前");
Object proceed= pjd.proceed();
logger.debug("around之后");
return proceed;
}
}
測驗
@Test
public void test( ){
//創建spring的容器并初始化
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");
String[] beanNameForType = classPathXmlApplicationContext.getBeanNamesForType(UserController.class);
System.out.println(Arrays.toString(beanNameForType));
UserController bean = (UserController) classPathXmlApplicationContext.getBean("userController");
bean.login("aa","123"); //這是 UserController 里寫好的login方法
classPathXmlApplicationContext.close();
}
輸出結果

因為沒有例外,所以 **afterThrowing **方法沒有執行
下面是一些切入點語法
直接精準到一個方法上面去
execution( public com.bing.entity.User com.bing.service.impl.UserServiceImpl.login(java.lang.String,java.lang.String))
任意權限修飾符
execution( com.bing.entity.User com.bing.service.impl.UserServiceImpl.login(java.lang.String,java.lang.String))
無回傳型別
execution( void com.bing.service.impl.UserServiceImpl.login(java.lang.String,java.lang.String))
有回傳型別
execution( !void com.bing.service.impl.UserServiceImpl.login(java.lang.String,java.lang.String))
任意回傳型別
execution( * com.bing.service.impl.UserServiceImpl.login(java.lang.String,java.lang.String))
任意引數
execution( * com.bing.service.impl.UserServiceImpl.login(..))
類中的任意方法
execution( * com.bing.service.impl.UserServiceImpl.*(..))
類中以指定內容開頭的方法
execution( * com.bing.service.impl.UserServiceImpl.select*(..))
包中的任意類的任意方法不包含子包下面的類
execution( * com.bing.service.impl.*.*(..))
包中及其下的任意類的任意方法
execution( * com.bing.service..*.*(..))
AOP還可以用XML方法實作,這里就不演示了,如果大家有興趣,可以自行百度實作
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/502836.html
標籤:其他
下一篇:C++函式指標使用
