日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

spring框架 AOP核心详解

發布時間:2025/3/8 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring框架 AOP核心详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  AOP稱為面向切面編程,在程序開發中主要用來解決一些系統層面上的問題,比如日志,事務,權限等待,Struts2的攔截器設計就是基于AOP的思想,是個比較經典的例子。

  一 AOP的基本概念

  (1)Aspect(切面):通常是一個類,里面可以定義切入點和通知

  (2)JointPoint(連接點):程序執行過程中明確的點,一般是方法的調用

  (3)Advice(通知):AOP在特定的切入點上執行的增強處理,有before,after,afterReturning,afterThrowing,around

  (4)Pointcut(切入點):就是帶有通知的連接點,在程序中主要體現為書寫切入點表達式

  (5)AOP代理:AOP框架創建的對象,代理就是目標對象的加強。Spring中的AOP代理可以使JDK動態代理,也可以是CGLIB代理,前者基于接口,后者基于子類

  如果想學習Java工程化、高性能及分布式、深入淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友可以加我的Java高級交流:854630135,群里有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給大家。

  二 Spring AOP

  Spring中的AOP代理還是離不開Spring的IOC容器,代理的生成,管理及其依賴關系都是由IOC容器負責,Spring默認使用JDK動態代理,在需要代理類而不是代理接口的時候,Spring會自動切換為使用CGLIB代理,不過現在的項目都是面向接口編程,所以JDK動態代理相對來說用的還是多一些。

  三 基于注解的AOP配置方式

  1.啟用@AsjectJ支持

  在applicationContext.xml中配置下面一句:

  

  2.通知類型介紹

  (1)Before:在目標方法被調用之前做增強處理,@Before只需要指定切入點表達式即可

  (2)AfterReturning:在目標方法正常完成后做增強,@AfterReturning除了指定切入點表達式后,還可以指定一個返回值形參名returning,代表目標方法的返回值

  (3)AfterThrowing:主要用來處理程序中未處理的異常,@AfterThrowing除了指定切入點表達式后,還可以指定一個throwing的返回值形參名,可以通過該形參名

  來訪問目標方法中所拋出的異常對象

  (4)After:在目標方法完成之后做增強,無論目標方法時候成功完成。@After可以指定一個切入點表達式

  (5)Around:環繞通知,在目標方法完成前后做增強處理,環繞通知是最重要的通知類型,像事務,日志等都是環繞通知,注意編程中核心是一個ProceedingJoinPoint

  3.例子:

  spring框架 AOP核心詳解

  (1)Operator.java -- 切面類

  @Componentbr/@Aspect

  public class Operator {

  @Pointcut(execution( com.aijava.springcode.service...*(..)))

  public void pointCut(){}

  @Before(pointCut())

  public void doBefore(JoinPoint joinPoint){

  System.out.println(AOP Before Advice...);

  }

  @After(pointCut())

  public void doAfter(JoinPoint joinPoint){

  System.out.println(AOP After Advice...);

  }

  @AfterReturning(pointcut=pointCut(),returning=returnVal)

  public void afterReturn(JoinPoint joinPoint,Object returnVal){

  System.out.println(AOP AfterReturning Advice: + returnVal);

  }

  @AfterThrowing(pointcut=pointCut(),throwing=error)

  public void afterThrowing(JoinPoint joinPoint,Throwable error){

  System.out.println(AOP AfterThrowing Advice... + error);

  System.out.println(AfterThrowing...);

  }

  @Around(pointCut())

  public void around(ProceedingJoinPoint pjp){

  System.out.println(AOP Aronud before...);

  try {

  pjp.proceed();

  } catch (Throwable e) {

  e.printStackTrace();

  }

  System.out.println(AOP Aronud after...);

  }

  }

  (2)UserService.java -- 定義一些目標方法

  @Service

  public class UserService {

  public void add(){

  System.out.println(UserService add());

  }

  public boolean delete(){

  System.out.println(UserService delete());

  return true;

  }

  public void edit(){

  System.out.println(UserService edit());

  int i = 5/0;

  }

  }

  (3).applicationContext.xml

  

  

  (4).Test.java

  public class Test {

  public static void main(String[] args) {

  ApplicationContext ctx = new ClassPathXmlApplicationContext(classpath:applicationContext.xml);

  UserService userService = (UserService) ctx.getBean(userService);

  userService.add();

  }

  }

  上面是一個比較簡單的測試,基本涵蓋了各種增強定義。注意:做環繞通知的時候,調用ProceedingJoinPoint的proceed()方法才會執行目標方法。

  4.通知執行的優先級

  進入目標方法時,先織入Around,再織入Before,退出目標方法時,先織入Around,再織入AfterReturning,最后才織入After。

  注意:Spring AOP的環繞通知會影響到AfterThrowing通知的運行,不要同時使用!同時使用也沒啥意義。

  如果想學習Java工程化、高性能及分布式、深入淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友可以加我的Java高級交流:854630135,群里有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給大家。

  5.切入點的定義和表達式

  切入點表達式的定義算是整個AOP中的核心,有一套自己的規范

  Spring AOP支持的切入點指示符:

  (1)execution:用來匹配執行方法的連接點

  A:@Pointcut(execution( com.aijava.springcode.service...*(..)))

  第一個表示匹配任意的方法返回值,..(兩個點)表示零個或多個,上面的第一個..表示service包及其子包,第二個表示所有類,第三個*表示所有方法,第二個..表示

  方法的任意參數個數

  B:@Pointcut(within(com.aijava.springcode.service.*))

  within限定匹配方法的連接點,上面的就是表示匹配service包下的任意連接點

  C:@Pointcut(this(com.aijava.springcode.service.UserService))

  this用來限定AOP代理必須是指定類型的實例,如上,指定了一個特定的實例,就是UserService

  D:@Pointcut(bean(userService))

  bean也是非常常用的,bean可以指定IOC容器中的bean的名稱

  后言: spring 的環繞通知和前置通知,后置通知有著很大的區別,主要有兩個重要的區別:

  1) 目標方法的調用由環繞通知決定,即你可以決定是否調用目標方法,而前置和后置通知 是不能決定的,他們只是在方法的調用前后執行通知而已,即目標方法肯定是要執行的。

  2) 環繞通知可以控制返回對象,即你可以返回一個與目標對象完全不同的返回值,雖然這很危險,但是你卻可以辦到。而后置方法是無法辦到的,因為他是在目標方法返回值后調用

  6.基于XML形式的配置方式

  開發中如果選用XML配置方式,通常就是POJO+XML來開發AOP,大同小異,無非就是在XML文件中寫切入點表達式和通知類型

  例子:

  (1)Log.java

  public class Log {

  private Integer id;

  //操作名稱,方法名

  private String operName;

  //操作人

  private String operator;

  //操作參數

  private String operParams;

  //操作結果 成功/失敗

  private String operResult;

  //結果消息

  private String resultMsg;

  //操作時間

  private Date operTime = new Date();

  setter,getter

  }

  (2).Logger.java

  /**

  日志記錄器 (AOP日志通知)

  */

  public class Logger {

  @Resource

  private LogService logService;

  public Object record(ProceedingJoinPoint pjp){

  Log log = new Log();

  try {

  log.setOperator(admin);

  String mname = pjp.getSignature().getName();

  log.setOperName(mname);

  //方法參數,本例中是User user

  Object[] args = pjp.getArgs();

  log.setOperParams(Arrays.toString(args));

  //執行目標方法,返回的是目標方法的返回值,本例中 void

  Object obj = pjp.proceed();

  if(obj != null){

  log.setResultMsg(obj.toString());

  }else{

  log.setResultMsg(null);

  }

  log.setOperResult(success);

  log.setOperTime(new Date());

  return obj;

  } catch (Throwable e) {

  log.setOperResult(failure);

  log.setResultMsg(e.getMessage());

  } finally{

  logService.saveLog(log);

  }

  return null;

  }

  }

  (3).applicationContext.xml

  

  

  

  

  

  注意切入點表達式,!bean(logService) 做日志通知的時候,不要給日志本身做日志,否則會造成無限循環!

  如果想學習Java工程化、高性能及分布式、深入淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友可以加我的Java高級交流:854630135,群里有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給大家。

  有關更詳細的Spring AOP知識,可以查看Spring官方文檔第9章Aspect Oriented Programming with Spring

  7.JDK動態代理介紹

  例子:

  (1)UserService.java

  public interface UserService {

  public void add();

  }

  (2)UserServiceImpl.java

  public class UserServiceImpl implements UserService{

  public void add() {

  System.out.println(User add()...);

  }

  }

  (3)ProxyUtils.java

  public class ProxyUtils implements InvocationHandler{

  private Object target;

  public ProxyUtils(Object target){

  this.target = target;

  }

  public Object getTarget() {

  return target;

  }

  public void setTarget(Object target) {

  this.target = target;

  }

  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

  System.out.println(do sth before...);

  method.invoke(target, args);

  System.out.println(do sth after...);

  return null;

  }

  }

  (4)Test.java

  public class Test {

  public static void main(String[] args) {

  UserService userService = new UserServiceImpl();

  ProxyUtils proxyUtils = new ProxyUtils(userService);

  UserService proxyObject = (UserService) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),UserServiceImpl.class.getInterfaces(), proxyUtils);

  proxyObject.add();

  }

  }

  JDK動態代理核心還是一個InvocationHandler,記住這個就行了。

?


轉載于:https://juejin.im/post/5c8b6a626fb9a049e6612377

總結

以上是生活随笔為你收集整理的spring框架 AOP核心详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。