成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Spring筆記03_AOP

blair / 2118人閱讀

摘要:介紹什么是在軟件業(yè),為的縮寫,意為面向切面編程,通過預(yù)編譯方式和運行期動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護的一種技術(shù)。切面是切入點和通知引介的結(jié)合。切面類權(quán)限校驗。。。

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

在軟件業(yè),AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,通過預(yù)編譯方式運行期動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護的一種技術(shù)。AOP是OOP(面向?qū)ο缶幊蹋┑难永m(xù),是軟件開發(fā)中的一個熱點,也是Spring框架中的一個重要內(nèi)容,是函數(shù)式編程的一種衍生范型。利用AOP可以對業(yè)務(wù)邏輯的各個部分進行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發(fā)的效率。

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

經(jīng)典應(yīng)用:事務(wù)管理、性能監(jiān)視、安全檢查、緩存 、日志等。

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

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

1.1.2 AOP實現(xiàn)原理

aop底層將采用代理機制進行實現(xiàn)

接口+實現(xiàn)類時:Spring采用JDK的動態(tài)代理Proxy

只有實現(xiàn)類時:Spring采用cglib字節(jié)碼增強。這種底層屬于繼承增強。

1.1.3 AOP術(shù)語【掌握】

Target :目標(biāo)類,需要被代理的類。本例中如:UserDao

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

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

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

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

Proxy :代理類,一個類被AOP織入增強后,就產(chǎn)生一個結(jié)果代理類。

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

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

小結(jié):

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

詳解如圖02:

1.2 AOP的底層實現(xiàn)(了解)

動態(tài)代理

JDK動態(tài)代理:只能對實現(xiàn)了接口的類產(chǎn)生代理

Cglib動態(tài)代理(第三方代理技術(shù)):對沒有實現(xiàn)接口的類產(chǎn)生代理對象,生成子類對象。

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

1.2.1 JDK動態(tài)代理

準(zhǔn)備工作:新建web項目,不需要導(dǎo)包

代理對象UserDao

package com.itzhouq.spring.demo1;

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

實現(xiàn)類

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產(chǎn)生UserDao的代理類

  package com.itzhouq.spring.demo1;
  
  import java.lang.reflect.InvocationHandler;
  import java.lang.reflect.Method;
  import java.lang.reflect.Proxy;
  
  /*
   * 使用JDK動態(tài)代理對UserDao產(chǎn)生代理
   */
  public class JDKProxy implements InvocationHandler {
      // 將被增強的對象傳遞到代理總
      private UserDao userDao;
      public JDKProxy(UserDao userDao) {
          this.userDao = userDao;
      }
      /*
       * 產(chǎn)生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("權(quán)限校驗==============");
              return method.invoke(userDao, args);
              
          }
          return method.invoke(userDao, args);
      }
  }

測試類

package com.itzhouq.spring.demo1;

import org.junit.Test;

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

1.2.2 Cglib動態(tài)代理

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

cglib的運行原理:在運行時創(chuàng)建目標(biāo)類的子類從而對目標(biāo)類進行增強。

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

目標(biāo)類:沒有實現(xiàn)接口

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動態(tài)代理
  */
 public class CglibProxy implements MethodInterceptor {
     
     private CustomerDao customerDao;
 
     public CglibProxy(CustomerDao customerDao) {
         this.customerDao = customerDao;
     }
     
     // 使用Cglib產(chǎn)生代理的方法
     public CustomerDao createProxy() {
         // 1. 創(chuàng)建cglib的核心類對象
         Enhancer enhancer = new Enhancer();
         // 2. 設(shè)置父類
         enhancer.setSuperclass(customerDao.getClass());
         // 3. 設(shè)置回調(diào)(類似于InvocationHandler對象)
         enhancer.setCallback(this);
         // 4. 創(chuàng)建代理對象
         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("權(quán)限校驗========");
             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();
          //權(quán)限校驗========
          //保存客戶
          //查找客戶
          //更新客戶
          //刪除客戶
      }
  }
1.2.3 總結(jié)

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

Spring AOP的底層是通過JDK動態(tài)代理或者Cglib動態(tài)代理技術(shù)為目標(biāo)bean執(zhí)行橫向織入的。

Spring會優(yōu)先使用Spring使用JDK代理方式進行代理

若目標(biāo)對象沒有實現(xiàn)任何接口,Spring容器會使用Cglib動態(tài)代理

標(biāo)記為final的方法不能被代理,因為無法進行覆蓋

Cglib動態(tài)代理,是針對的目標(biāo)類產(chǎn)生子類,所以目標(biāo)類不能被final修飾。

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

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

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

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

Spring兩種開發(fā)方式

Spring傳統(tǒng)方式(棄用)。

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

2.2 AOP入門開發(fā) 2.2.1 準(zhǔn)備工程和jar包

除去基本的6個包,在web項目中添加aop開發(fā)的相關(guān)jar包

AOP聯(lián)盟規(guī)范包:..spring相關(guān)依賴包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相關(guān)依賴包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 編寫目標(biāo)類并完成配置

目標(biāo)接口

package com.itzhouq.spring.demo3;

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

目標(biāo)類

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("刪除商品");
    }

}

配置目標(biāo)對象


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("權(quán)限校驗。。。");
              }
          }
2.2.6 將切面類交給Spring

    
      

2.2.7 通過AOP的配置實現(xiàn)動態(tài)代理

    
        
        
        
        
            
        
    
2.2.8 測試類中運行結(jié)果,save實現(xiàn)了增強
@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();
//        權(quán)限校驗。。。
//        保存商品
//        更新商品
//        查找商品
//        刪除商品

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

配置



    

在目標(biāo)方法執(zhí)行之前進行操作

可以獲得切入點的信息

比如在切面類中加入?yún)?shù)JoinPoint

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

測試打印的效果

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

2.3.2 后置通知:

在目標(biāo)方法之后操作,可以獲得返回值

修改接口ProductDao和實現(xiàn)類ProductDaoImpl類的delete方法的返回值為String

配置后置通知


    
        
        
        
        
        
            
            
            
            
        
    

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

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

測試

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

2.3.3 環(huán)繞通知:

在目標(biāo)方法執(zhí)行之前 和之后進行操作

環(huán)繞通知可以組織目標(biāo)方法的執(zhí)行

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

在切面類中添加一個方法用來測試環(huán)繞通知

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

配置環(huán)繞通知


        
        
        
        
        
        
            
            
            
            
            
            
        
    

測試

//        權(quán)限校驗。。。execution(void com.itzhouq.spring.demo3.ProductDao.save())
//        保存商品
//        環(huán)繞前通知===========
//        更新商品
//        環(huán)繞后通知=========
//        查找商品
//        刪除商品
//        日志記錄=======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);
      }

配置異常通知


        
        
        
        
        
        
        
            
            
            
            
            
            
            
            
        
    

測試

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

2.3.5 最終通知:

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

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

配置最終通知


            

測試

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

2.3.6 引介通知(不用會) 2.4 切入點表達式【掌握】
1.execution()  用于描述方法【掌握】
    語法:execution(修飾符  返回值  包.類.方法名(參數(shù)) 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結(jié)尾的類
            User*                           以User開頭的類
            *                               任意的類
        方法名,不能省略
            addUser                         固定的方法名
            add*                            以add開頭的方法名
            *Do                             以Do結(jié)尾的方法名
            *                               任意的方法名
        (參數(shù))
            ()                              無參
            (int)                           一個整型
            (int, int)                      兩個整型
            (..)                            參數(shù)任意
        throws,[可以省略],一般省略。

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

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

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/74401.html

相關(guān)文章

  • Spring筆記04_AOP注解開發(fā)_模板_事務(wù)

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

    youkede 評論0 收藏0
  • 慕課網(wǎng)_《探秘Spring AOP》學(xué)習(xí)總結(jié)

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

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

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

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

    摘要:接口日志有啥用在我們?nèi)粘5拈_發(fā)過程中,我們可以通過接口日志去查看這個接口的一些詳細信息。在切入點返回內(nèi)容之后切入內(nèi)容可以用來對處理返回值做一些加工處理。 接口日志有啥用 在我們?nèi)粘5拈_發(fā)過程中,我們可以通過接口日志去查看這個接口的一些詳細信息。比如客戶端的IP,客戶端的類型,響應(yīng)的時間,請求的類型,請求的接口方法等等,我們可以對這些數(shù)據(jù)進行統(tǒng)計分析,提取出我們想要的信息。 怎么拿到接口...

    Youngdze 評論0 收藏0
  • Spring入門IOC和AOP學(xué)習(xí)筆記

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

    wenyiweb 評論0 收藏0

發(fā)表評論

0條評論

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