国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Spring筆記03_AOP

blair / 2068人閱讀

摘要:介紹什么是在軟件業,為的縮寫,意為面向切面編程,通過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。切面是切入點和通知引介的結合。切面類權限校驗。。。

1. AOP 1.1 AOP介紹 1.1.1 什么是AOP

在軟件業,AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,通過預編譯方式運行期動態代理實現程序功能的統一維護的一種技術。AOP是OOP(面向對象編程)的延續,是軟件開發中的一個熱點,也是Spring框架中的一個重要內容,是函數式編程的一種衍生范型。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發的效率。

AOP采取橫向抽取機制,取代了傳統縱向繼承體系重復性代碼。如下圖所示:

經典應用:事務管理、性能監視、安全檢查、緩存 、日志等。

Spring AOP使用純Java實現,不需要專門的編譯過程和類加載器,在運行期通過代理方式向目標類織入增強代碼。

AspectJ是一個基于Java語言的AOP框架,從Spring2.0開始,Spring AOP引入對Aspect的支持,AspectJ擴展了Java語言,提供了一個專門的編譯器,在編譯時提供橫向代碼的織入。

1.1.2 AOP實現原理

aop底層將采用代理機制進行實現

接口+實現類時:Spring采用JDK的動態代理Proxy

只有實現類時:Spring采用cglib字節碼增強。這種底層屬于繼承增強。

1.1.3 AOP術語【掌握】

Target :目標類,需要被代理的類。本例中如:UserDao

Joinpoint(連接點) :所謂連接點是指那些可能被攔截到的點。在spring中,這些點指的是方法,因為spring只支持方法類型的連接點。本例中如:UserDao的所有的方法

PointCut 切入點 :所謂切入點是指我們要對哪些Joinpoint進行攔截,即已經被增強的連接點。例如:save()

Advice :通知/增強,增強的代碼。例如:checkPri()
所謂通知是指攔截到Joinpoint之后所要做的事情就是通知,通知分為前置通知、后置通知、異常通知、最終通知、環繞通知(即切面要完成的功能)。

Weaving(織入) :是指把通知/增強advice應用到目標對象target來創建新的代理對象proxy的過程。
spring采用動態代理織入,而AspectJ采用編譯期織入和類裝在期織入。

Proxy :代理類,一個類被AOP織入增強后,就產生一個結果代理類。

Aspect(切面) : 是切入點Pointcut和通知Advice(引介)的結合。

Introduction(引介) :引介是一種特殊的通知,在不修改類代碼的前提下,Introduction 可以在運行期為類動態地添加一些方法或Field。

小結:

一個線是一個特殊的面。
一個切入點和一個通知,組成成一個特殊的面。
詳解如圖01:

詳解如圖02:

1.2 AOP的底層實現(了解)

動態代理

JDK動態代理:只能對實現了接口的類產生代理

Cglib動態代理(第三方代理技術):對沒有實現接口的類產生代理對象,生成子類對象。

代理知識點參考:https://www.cnblogs.com/itzho...

1.2.1 JDK動態代理

準備工作:新建web項目,不需要導包

代理對象UserDao

package com.itzhouq.spring.demo1;

public interface UserDao {
    public void save();
    public void update();
    public void find();
    public void delete();
}

實現類

package com.itzhouq.spring.demo1;

public class UserDaoImpl implements UserDao {

    @Override
    public void save() {
        System.out.println("保存用戶");
    }

    @Override
    public void update() {
        System.out.println("更新用戶");
    }

    @Override
    public void find() {
        System.out.println("查找用戶");
    }

    @Override
    public void delete() {
        System.out.println("刪除用戶");
    }

}

使用JDK產生UserDao的代理類

  package com.itzhouq.spring.demo1;
  
  import java.lang.reflect.InvocationHandler;
  import java.lang.reflect.Method;
  import java.lang.reflect.Proxy;
  
  /*
   * 使用JDK動態代理對UserDao產生代理
   */
  public class JDKProxy implements InvocationHandler {
      // 將被增強的對象傳遞到代理總
      private UserDao userDao;
      public JDKProxy(UserDao userDao) {
          this.userDao = userDao;
      }
      /*
       * 產生UserDao代理的方法
       */
      public UserDao createProxy() {
          UserDao userDaoProxy = (UserDao) Proxy.newProxyInstance(
                  userDao.getClass().getClassLoader(),
                  userDao.getClass().getInterfaces(),
                  this);
          return userDaoProxy;
      }
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          // 判斷方法名是不是save
          if("save".equals(method.getName())) {
              // 增強
              System.out.println("權限校驗==============");
              return method.invoke(userDao, args);
              
          }
          return method.invoke(userDao, args);
      }
  }

測試類

package com.itzhouq.spring.demo1;

import org.junit.Test;

public class SpringDemo1 {
    
    @Test
    //JDK動態代理
    public void test1() {
        UserDao userDao = new UserDaoImpl();
        // 創建代理
        UserDao proxy = new JDKProxy(userDao).createProxy();
        proxy.save();
        proxy.find();
        proxy.delete();
        proxy.update();
        //權限校驗==============
        //保存用戶
        //查找用戶
        //刪除用戶
        //更新用戶
    }
}

1.2.2 Cglib動態代理

Cglib是第三方開源代碼生成類庫,動態添加類的屬性和方法

cglib的運行原理:在運行時創建目標類的子類從而對目標類進行增強。

因為Spring核心包中包含了cglib的包,所以引入Spring的4+2必備包就可以使用Cglib了

目標類:沒有實現接口

package com.itzhouq.spring.demo2;

public class CustomerDao {
    public void save() {
        System.out.println("保存客戶");
    }
    public void update() {
        System.out.println("更新客戶");
    }
    public void find() {
        System.out.println("查找客戶");
    }
    public void delete() {
        System.out.println("刪除客戶");
    }
}

Cglib代理類

 package com.itzhouq.spring.demo2;
 
 import java.lang.reflect.Method;
 
 import org.springframework.cglib.proxy.Enhancer;
 import org.springframework.cglib.proxy.MethodInterceptor;
 import org.springframework.cglib.proxy.MethodProxy;
 
 /*
  * Cglib動態代理
  */
 public class CglibProxy implements MethodInterceptor {
     
     private CustomerDao customerDao;
 
     public CglibProxy(CustomerDao customerDao) {
         this.customerDao = customerDao;
     }
     
     // 使用Cglib產生代理的方法
     public CustomerDao createProxy() {
         // 1. 創建cglib的核心類對象
         Enhancer enhancer = new Enhancer();
         // 2. 設置父類
         enhancer.setSuperclass(customerDao.getClass());
         // 3. 設置回調(類似于InvocationHandler對象)
         enhancer.setCallback(this);
         // 4. 創建代理對象
         CustomerDao proxy = (CustomerDao) enhancer.create();
         return proxy;
     }
 
     @Override
     public Object intercept(Object proxy, Method method, Object[] arg, MethodProxy methodProxy) 
             throws Throwable {
         // 判斷方法是否為save
         if("save".equals(method.getName())) {
             // 增強
             System.out.println("權限校驗========");
             return methodProxy.invokeSuper(proxy, arg);
         }
         return methodProxy.invokeSuper(proxy, arg);
     }
 }

測試

  package com.itzhouq.spring.demo2;
  
  import org.junit.Test;
  
  public class SpringDemo2 {
      /*
       * cglib的測試
       */
      
      @Test
      public void test1() {
          CustomerDao customerDao = new CustomerDao();
          CustomerDao proxy = new CglibProxy(customerDao).createProxy();
          proxy.save();
          proxy.find();
          proxy.update();
          proxy.delete();
          //權限校驗========
          //保存客戶
          //查找客戶
          //更新客戶
          //刪除客戶
      }
  }
1.2.3 總結

Spring在運行期,生成動態代理對象,不需要特殊的編譯器。

Spring AOP的底層是通過JDK動態代理或者Cglib動態代理技術為目標bean執行橫向織入的。

Spring會優先使用Spring使用JDK代理方式進行代理

若目標對象沒有實現任何接口,Spring容器會使用Cglib動態代理

標記為final的方法不能被代理,因為無法進行覆蓋

Cglib動態代理,是針對的目標類產生子類,所以目標類不能被final修飾。

Spring只支持方法連接點,不提供屬性連接。

2. Spring的AOP的開發(AspectJ的XML方式) 2.1 Spring的AOP簡介

AOP思想最早是由AOP聯盟組織提出。Spring是使用這種思想最好的框架。

Spring的AOP有自己的實現方式(非常繁瑣)。AspectJ是一個AOP框架,Spring引入AspectJ作為自身AOP的開發

Spring兩種開發方式

Spring傳統方式(棄用)。

Spring基于AspectJ的AOP開發方式(使用)。

2.2 AOP入門開發 2.2.1 準備工程和jar包

除去基本的6個包,在web項目中添加aop開發的相關jar包

AOP聯盟規范包:..spring相關依賴包spring-framework-3.0.2.RELEASE-dependenciesorg.aopalliancecom.springsource.org.aopalliance1.0.0com.springsource.org.aopalliance-1.0.0.jar

AOP包:..spring-framework-4.2.4.RELEASE-distspring-framework-4.2.4.RELEASElibsspring-aop-4.2.4.RELEASE.jar

AspectJ包:..spring相關依賴包spring-framework-3.0.2.RELEASE-dependenciesorg.aspectjcom.springsource.org.aspectj.weaver1.6.8.RELEASEcom.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

Spring和ASpectJ整合包:..spring-framework-4.2.4.RELEASE-distspring-framework-4.2.4.RELEASElibsspring-aspects-4.2.4.RELEASE.jar

Spring整合JUnit單元測試包:..spring-framework-4.2.4.RELEASE-distspring-framework-4.2.4.RELEASElibsspring-test-4.2.4.RELEASE.jar

2.2.2 引入Spring的配置文件

引入aop的約束

約束的位置:../spring-framework-4.2.4.RELEASE-dist/spring-framework-4.2.4.RELEASE/docs/spring-framework-reference/html/xsd-configuration.html 40.2.7 the aop schema



2.2.3 編寫目標類并完成配置

目標接口

package com.itzhouq.spring.demo3;

public interface ProductDao {
    public void save();
    public void update();
    public void find();
    public void delete();
}

目標類

package com.itzhouq.spring.demo3;

public class ProductDaoImpl implements ProductDao {

    @Override
    public void save() {
        System.out.println("保存商品");
    }

    @Override
    public void update() {
        System.out.println("更新商品");
    }

    @Override
    public void find() {
        System.out.println("查找商品");
    }

    @Override
    public void delete() {
        System.out.println("刪除商品");
    }

}

配置目標對象


2.2.4 測試類
package com.itzhouq.spring.demo3;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/*
 * AOP入門
 */
@RunWith(SpringJUnit4ClassRunner.class)    //這兩個注釋就是Spring整合了JUnit單元測試
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDemo3 {
    
    //注入productDao
    @Resource(name="productDao")
    private ProductDao productDao;
    
    @Test
    public void test1() {
        productDao.save();
        productDao.update();
        productDao.find();
        productDao.delete();
//        保存商品
//        更新商品
//        查找商品
//        刪除商品
    }
}

下面需要對save()方法增強

2.2.5 編寫一個切面類

切面:多個通知和多個切入點的組合。

 package com.itzhouq.spring.demo3;
          /*
           * 切面類
           */
          public class MyAspectXML {
              public void checkPri() {
                  System.out.println("權限校驗。。。");
              }
          }
2.2.6 將切面類交給Spring

    
      

2.2.7 通過AOP的配置實現動態代理

    
        
        
        
        
            
        
    
2.2.8 測試類中運行結果,save實現了增強
@RunWith(SpringJUnit4ClassRunner.class)    //這兩個注釋就是Spring整合了JUnit單元測試
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDemo3 {
    
    //注入productDao
    @Resource(name="productDao")
    private ProductDao productDao;
    
    @Test
    public void test1() {
        productDao.save();
        productDao.update();
        productDao.find();
        productDao.delete();
//        權限校驗。。。
//        保存商品
//        更新商品
//        查找商品
//        刪除商品

    }
}
2.3 Spring中的通知類型 2.3.1 前置通知

配置



    

在目標方法執行之前進行操作

可以獲得切入點的信息

比如在切面類中加入參數JoinPoint

public class MyAspectXML {
    
    public void checkPri(JoinPoint joinPoint) {
        System.out.println("權限校驗。。。"+joinPoint);
    }
}

測試打印的效果

//        權限校驗。。。execution(void com.itzhouq.spring.demo3.ProductDao.save())
//        保存商品
//        更新商品
//        查找商品
//        刪除商品

2.3.2 后置通知:

在目標方法之后操作,可以獲得返回值

修改接口ProductDao和實現類ProductDaoImpl類的delete方法的返回值為String

配置后置通知


    
        
        
        
        
        
            
            
            
            
        
    

在后置切面類中添加記錄日志的方法

 /*
       * 后置通知演示
       */
      public void writeLog(Object result) {
          System.out.println("日志記錄======="+result);
      }

測試

權限校驗。。。execution(void com.itzhouq.spring.demo3.ProductDao.save())
//        保存商品
//        更新商品
//        查找商品
//        刪除商品
//        日志記錄=======kkk

2.3.3 環繞通知:

在目標方法執行之前 和之后進行操作

環繞通知可以組織目標方法的執行

舉例:需求---在修改方法update前后添加性能監控

在切面類中添加一個方法用來測試環繞通知

/**
       * 性能監控
       * @throws Throwable 
       */
      public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
          System.out.println("環繞前通知===========");
          Object obj = joinPoint.proceed();//這一步相當于執行目標程序
          System.out.println("環繞后通知=========");
          return obj;
      }

配置環繞通知


        
        
        
        
        
        
            
            
            
            
            
            
        
    

測試

//        權限校驗。。。execution(void com.itzhouq.spring.demo3.ProductDao.save())
//        保存商品
//        環繞前通知===========
//        更新商品
//        環繞后通知=========
//        查找商品
//        刪除商品
//        日志記錄=======kkk

2.3.4 異常拋出通知:

在程序拋出異常時候進行操作,可以得到異常信息

在find方法上模擬一個異常

@Override
    public void find() {
        System.out.println("查找商品");
        int i = 1 / 0;
    }

切面類中添加一個方法用于測試異常拋出通知

 /*
       * 異常拋出通知
       */
      public void afterThrowing(Throwable ex) {
          System.out.println("異常拋出通知=======" + ex);
      }

配置異常通知


        
        
        
        
        
        
        
            
            
            
            
            
            
            
            
        
    

測試

//        權限校驗。。。execution(void com.itzhouq.spring.demo3.ProductDao.save())
//        保存商品
//        環繞前通知===========
//        更新商品
//        環繞后通知=========
//        查找商品
//        異常拋出通知=======java.lang.ArithmeticException: / by zero

2.3.5 最終通知:

在切面類中添加方法測試最終通知

/*
       * 最終通知:相當于finally代碼塊中的內容
       */
      public void after() {
          System.out.println("最終通知=========");
      }

配置最終通知


            

測試

無論是否有異常,最終通知都會執行。

2.3.6 引介通知(不用會) 2.4 切入點表達式【掌握】
1.execution()  用于描述方法【掌握】
    語法:execution(修飾符  返回值  包.類.方法名(參數) throws異常)
        修飾符,一般省略
            public      公共方法
            *           任意
        返回值,不能省略
            void        返回沒有值
            String      返回值字符串
            *           任意
        包,[可以省略]
            com.itheima.crm                 固定的包
            com.itheima.crm.*.service       crm包下面的任意子包,固定目錄service(例如:com.itheima.crm.staff.service)
            com.itheima.crm..               crm包下面的所有子包(含自己)
            com.itheima.crm.*.service..     crm包下面的任意子包,固定目錄service,service目錄任意包(含自己)
        類,[可以省略]
            UserServiceImpl                 指定的類
            *Impl                           以Impl結尾的類
            User*                           以User開頭的類
            *                               任意的類
        方法名,不能省略
            addUser                         固定的方法名
            add*                            以add開頭的方法名
            *Do                             以Do結尾的方法名
            *                               任意的方法名
        (參數)
            ()                              無參
            (int)                           一個整型
            (int, int)                      兩個整型
            (..)                            參數任意
        throws,[可以省略],一般省略。

    綜合案例1:
        execution(* com.itheima.crm.*.service..*.*(..))
    綜合案例2:
        

2.within:匹配包或子包中的方法(了解)
    within(com.itheima.aop..*)
3.this:匹配實現了接口的代理對象中的方法(了解)
    this(com.itheima.aop.user.UserDAO)
4.target:匹配實現了接口的目標對象中的方法(了解)
    target(com.itheima.aop.user.UserDAO)
5.args:匹配參數格式符合標準的方法(了解)
    args(int, int)
6.bean(id):對指定的bean所有的方法(了解)
    bean("userServiceId")

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/74401.html

相關文章

  • Spring筆記04_AOP注解開發_模板_事務

    摘要:后置增強周杰倫環繞通知在切面類中添加以下方法環繞通知環繞前增強環繞前增強測試前置增強保存訂單。。。不使用事務管理。 1. Spring基于AspectJ的注解的AOP開發 1. 1 SpringAOP的注解入門 創建項目,導入jar包 需要導入Spring基礎包4+2 需要導入AOP聯盟包、AspectJ包、Spring整合Aspect包Spring-aop包 Spring整合單...

    youkede 評論0 收藏0
  • 慕課網_《探秘Spring AOP》學習總結

    時間:2017年09月03日星期日說明:本文部分內容均來自慕課網。@慕課網:http://www.imooc.com 教學源碼:https://github.com/zccodere/s...學習源碼:https://github.com/zccodere/s... 第一章:課程介紹 1-1 面向切面 課程章節 概覽 AOP使用 AOP原理 AOP開源運用 課程實戰 課程總結 面向切面編程是一種...

    Tony_Zby 評論0 收藏0
  • Spring框架學習筆記(一):官方文檔介紹,IoC與AOP概念學習

    摘要:構造函數注入通過調用類的構造函數,將接口實現類通過構造函數變量傳入。而在中,其使用橫切技術,將這類代碼從原屬的封裝對象中提取出來,封裝到一個可重用模塊中,稱為。 最近實習用到Spring的開發框架,但是之前沒有接觸過,因此希望利用網上的資源來學習以下。 Spring官方給出了非常全面的介紹,非常適合我這種完全的小白……在這一系列學習中,我閱讀的主要資源是5.1.2 Reference ...

    mindwind 評論0 收藏0
  • Spring Boot 2.x(十一):AOP實戰--打印接口日志

    摘要:接口日志有啥用在我們日常的開發過程中,我們可以通過接口日志去查看這個接口的一些詳細信息。在切入點返回內容之后切入內容可以用來對處理返回值做一些加工處理。 接口日志有啥用 在我們日常的開發過程中,我們可以通過接口日志去查看這個接口的一些詳細信息。比如客戶端的IP,客戶端的類型,響應的時間,請求的類型,請求的接口方法等等,我們可以對這些數據進行統計分析,提取出我們想要的信息。 怎么拿到接口...

    Youngdze 評論0 收藏0
  • Spring入門IOC和AOP學習筆記

    摘要:入門和學習筆記概述框架的核心有兩個容器作為超級大工廠,負責管理創建所有的對象,這些對象被稱為。中的一些術語切面切面組織多個,放在切面中定義。 Spring入門IOC和AOP學習筆記 概述 Spring框架的核心有兩個: Spring容器作為超級大工廠,負責管理、創建所有的Java對象,這些Java對象被稱為Bean。 Spring容器管理容器中Bean之間的依賴關系,使用一種叫做依賴...

    wenyiweb 評論0 收藏0

發表評論

0條評論

blair

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<