AOP猛快糙入門

學習AOP已經(jīng)很多年了,但是想起來總有點模糊,現(xiàn)在做下梳理,用最簡單直接的方式做個總結(jié)。
一定要動手!?。。。。。。。。。。。。?!
使用SpringBoot項目,首先添加maven依賴

 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-aop</artifactId>
 </dependency>

先認識有幾個核心概念:
AOP:Aspect Oriented Programming,面向切面編程。
連接點(Joinpoint):被切入的方法。
增強(Advice):一共有5種

  • @Before:前置增強,就是在目標方法執(zhí)行之前執(zhí)行;
  • @AfterReturning:后置增強,方法退出時執(zhí)行;
  • @AfterThrowing:有異常時該方法執(zhí)行;
  • @After:最終增強,無論什么情況都會執(zhí)行;
  • @Afround:環(huán)繞增強

切點(Pointcut):標記被切入的方法,連接了連接點和增強。

@Component
@Aspect
public class WorkAspect {

   // 第一種方式:直接使用切點表達式
   @Before("execution(* com.example.aop.Worker.work())")
   @Order(1)
   public void before1(JoinPoint joinPoint) {
       System.out.println("before1: " + joinPoint.getSignature());
   }

   // 第二種方式: 切點(表達式)
   @Pointcut("execution(* com.example.aop.Worker.work())")
   public void point() {
   }

   @Before("point()")
   @Order(2)
   public void before2(JoinPoint joinPoint) {
       System.out.println("before2: " + joinPoint.getSignature());
   }

   // 第三種方式: 切點(注解)
   @Pointcut("@annotation(com.example.aop.Cache)")
   public void point2() {

   }

   @Order(3)
   @Before("point2()")
   public void before3(JoinPoint joinPoint) {
       System.out.println("before3: " + joinPoint.getSignature());
   }
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface Cache {
}


@Component
public class Worker {

   @Cache
   public void work() {
       System.out.println("cnt: " + (++cnt));
   }

   private int cnt;

   public int getCnt() {
       return cnt;
   }

   public void setCnt(int cnt) {
       this.cnt = cnt;
   }

   @Override
   public String toString() {
       return "Work{" +
               "cnt=" + cnt +
               '}';
   }
}

再看下測試代碼:

@ComponentScan("com.example.aop")
@Configuration
@EnableAspectJAutoProxy
public class Config {
}

public class AopMain {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContex =
                new AnnotationConfigApplicationContext(Config.class);
        Worker worker = applicationContex.getBean(Worker.class);
        worker.work();
    }
}

測試結(jié)果:
before1: void com.example.aop.Worker.work()
before2: void com.example.aop.Worker.work()
before3: void com.example.aop.Worker.work()
cnt: 1

2019-03-13深入:
代理類是一個空殼(或外觀),它背后才是真正的類,通常稱為目標類。由此得出代理類要包含目標類。

當進入目標對象的方法后,執(zhí)行的上下文已經(jīng)變成目標對象本身了,因為目標對象的代碼是我們自己寫的,和事務沒有半毛錢關系,此時你再調(diào)用帶注解的方法,照樣沒有事務,只是一個普通的方法調(diào)用而已。

@Transactional:Spring選擇讓protected方法和package方法不支持事務,所以只有public方法支持事務。
只要是以代理方式實現(xiàn)的聲明式事務,無論是JDK動態(tài)代理,還是CGLIB直接寫字節(jié)碼生成代理,都只有public方法上的事務注解才起作用。
而且必須在代理類外部調(diào)用才行,如果直接在目標類里面調(diào)用,事務照樣不起作用。

//是否是JDK動態(tài)代理
System.out.println("isJdkDynamicProxy => " + AopUtils.isJdkDynamicProxy(exampleService));
//是否是CGLIB代理
System.out.println("isCglibProxy => " + AopUtils.isCglibProxy(exampleService));
//代理類的類型
System.out.println("proxyClass => " + exampleService.getClass());
//代理類的父類的類型
System.out.println("parentClass => " + exampleService.getClass().getSuperclass());
//代理類的父類實現(xiàn)的接口
System.out.println("parentClass's interfaces => " + Arrays.asList(exampleService.getClass().getSuperclass().getInterfaces()));
//代理類實現(xiàn)的接口
System.out.println("proxyClass's interfaces => " + Arrays.asList(exampleService.getClass().getInterfaces()));
//代理對象
System.out.println("proxy => " + exampleService);
//目標對象
System.out.println("target => " + AopProxyUtils.getSingletonTarget(exampleService));
//代理對象和目標對象是不是同一個
System.out.println("proxy == target => " + (exampleService == AopProxyUtils.getSingletonTarget(exampleService)));
//目標類的類型
System.out.println("targetClass => " + AopProxyUtils.getSingletonTarget(exampleService).getClass());
//目標類實現(xiàn)的接口
System.out.println("targetClass's interfaces => " + Arrays.asList(AopProxyUtils.getSingletonTarget(exampleService).getClass().getInterfaces()));

參考:【面試】我是如何在面試別人Spring事務時“套路”對方的

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • Spring的AOPAOP的基本概念基于注解的“零配置”方式定義切面Bean定義Before增強處理定義After...
    漸丶忘閱讀 1,654評論 0 0
  • IoC 容器 Bean 的作用域 自定義作用域?qū)崿F(xiàn) org.springframework.beans.facto...
    Hsinwong閱讀 2,614評論 0 7
  • AOP實現(xiàn)可分為兩類(按AOP框架修改源代碼的時機): 靜態(tài)AOP實現(xiàn):AOP框架在編譯階段對程序進行修改,即實現(xiàn)...
    數(shù)獨題閱讀 2,399評論 0 22
  • AOP稱為面向切面編程,在程序開發(fā)中主要用來解決一些系統(tǒng)層面上的問題,比如日志,事務,權限等待,Struts2的攔...
    程序員日常填坑閱讀 1,014評論 0 0
  • Spring 的 AOP 支持 Spring 的 AOP 代理由 Spring 的 IoC 容器負責生成、管理,其...
    WesleyLien閱讀 1,447評論 0 1

友情鏈接更多精彩內(nèi)容