1. 程式人生 > >spring03 AOP、各種通知、一/多個切面例子

spring03 AOP、各種通知、一/多個切面例子





一、 springAOP


       1、作用: 使得事務、日誌、安全性框架、許可權、目標方法之間完全是鬆耦合的
       
       2、組成
              1、切面:   事務、日誌、安全性框架、許可權等都是切面
              2、通知:   切面中的方法就是通知
              3、目標類 
              4、切入點   只有符合切入點,才能讓通知和目標方法結合在一起
              5、織入:   形成代理物件的方法的過程
              注:代理物件的方法就是通知和目標方法的結合體
              
       3、相對於動態代理,省略了寫攔截器的過程
       
       4、切入點表示式詳解
       
              

        
        
       5、springAOP的具體載入步驟:
             1、當spring容器啟動的時候,載入了spring的配置檔案
             2、為配置檔案中所有的bean建立物件
             3、spring容器會解析aop:config的配置 
                   解析切入點表示式,用切入點表示式和納入spring容器中的bean做匹配
                      如果匹配成功,則會為該bean建立代理物件,代理物件的方法=目標方法+通知
                      如果匹配不成功,不會建立代理物件
             4、在客戶端利用context.getBean獲取物件時,如果該物件有代理物件則返回代理物件,
                      如果無代理物件,則返回目標物件


             5、如果目標類沒有實現介面,則spring容器會採用cglib的方式產生代理物件,
                      如果實現了介面,會採用jdk的方式
       
              
       6、各種通知詳解
             1、前置通知
                  1、在目標方法執行之前執行
                  2、無論目標方法是否丟擲異常,都執行,因為在執行前置通知的時候,目標方法還沒有執行,還沒有遇到異常
                  例:  
                      ------------------------------------------------------------------------------
                      <aop:before method="beginTransaction" pointcut-ref="perform"/>
                      
                      // 前置通知
                      public void beginTransaction(){
                          System.out.println("before inform");
                          this.transaction = sessionFactory.getCurrentSession().beginTransaction();      
                      }
                      ------------------------------------------------------------------------------
                  
                  
             2、後置通知
                  1、在目標方法執行之後執行
                  2、當目標方法遇到異常,後置通知將不再執行
                  3、後置通知可以接受目標方法的返回值,但是必須注意:
                      後置通知的引數的型別為Object,且名稱和配置檔案中returning="var"的值是一致的
                  例:
                      ------------------------------------------------------------------------------
                      不帶引數的
                          <aop:after-returning method="commit" pointcut-ref="perform" />
                          
                          // 後置通知
                          public void commit(){
                              System.out.println("after return inform");
                              this.transaction.commit();
                          }
                          
                          // 不帶返回值的目標方法
                          public void savePerson(Person person) {
                              sessionFactory.getCurrentSession().save(person);
                          }
                        
                        
                      帶引數的
                          <aop:after-returning method="commit" pointcut-ref="perform" returning="var"/>
                          
                          public void commit(Object var){
                              System.out.println("after return inform");
                              System.out.println(var);
                              this.transaction.commit();
                          }
                          
                          // 帶返回值的目標方法
                          public String savePerson(Person person) {
                            //int i = 1/0;
                              System.out.println("目標方法");
                              return "返回值";
                          }
                      ------------------------------------------------------------------------------
                        
                           
             3、最終通知:
                  1、在目標方法執行之後執行
                  2、無論目標方法是否丟擲異常,都執行,因為相當於finally
                  例:
                      ------------------------------------------------------------------------------
                        <aop:after method="fianllyMethod" pointcut-ref="perform"/>
                        
                        public void fianllyMethod(){
                            System.out.println("finally inform");
                        }
                      ------------------------------------------------------------------------------
                  
                  
             4、異常通知
                  1、接受目標方法丟擲的異常資訊
                  2、步驟
                       在異常通知方法中有一個引數Throwable  ex
                       在配置檔案中
                          <aop:after-throwing method="throwingMethod" pointcut-ref="perform" throwing="ex"/>
                       注: throwing也要和切面中的異常通知的型別為Throable的引數名稱保持一致
                  例:
                      -------------------------------------------------------------------------------
                        <aop:after-throwing method="throwingMethod" pointcut-ref="perform" throwing="ex"/>
                        
                        public void throwingMethod(Throwable ex){
                            System.out.println(ex.getMessage());
                        }
                        
                        // 目標類
                        public void savePerson(Person person) {
                            int i = 1/0;
                            sessionFactory.getCurrentSession().save(person);
                        }
                      -------------------------------------------------------------------------------
                  
                          
                          
             5、環繞通知
                  1、環繞通知可以控制目標方法的執行
                      方式: 在環繞通知中加一個引數:
                            org.aspectj.lang.JoinPoint包中的ProceedingJoinPoint joinPoint
                            然後在環繞通知中顯示呼叫ProceedingJoinPoint的proceed()方法,,則執行目標方法
                  2、同時,各種通知若加JoinPoint引數(org.aspectj.lang.JoinPoint包),還可以獲取目標方法的資訊
                  例:
                      -------------------------------------------------------------------------------
                      不呼叫目標方法:
                          <aop:around method="aroundMethod" pointcut-ref="perform" />
                          
                          public void aroundMethod(){
                              System.out.println("around inform");  
                          }
                      
                          // 目標方法 注: 此時未呼叫目標方法
                          public String savePerson(Person person) {
                              System.out.println("目標方法");
                              return "返回值";
                          }
                      
                      
                      呼叫目標方法:
                          <aop:around method="aroundMethod" pointcut-ref="perform" />
                          
                          public void aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable{
                              joinPoint.proceed(); // 顯示的呼叫目標方法的執行,可以控制目標方法是否執行
                              System.out.println("around inform with targetMethod");
                              System.out.println("目標方法的方法名:"+joinPoint.getSignature().getName()); 
                          }
                          
                          // 目標方法: 注: 此時呼叫了目標方法
                          public String savePerson(Person person) {
                              System.out.println("目標方法");
                              return "返回值";
                          }
                      -------------------------------------------------------------------------------
       
       
       
       7、例1: 一個切面
            --------------------------------------------------------------------------------
                public class Person implements Serializable {
                    private Long pid;
                    private String pname;
                    private String psex;
                }
                
                // 介面
                public interface PersonDao {
                    public void savePerson(Person person);
                }
                
                // 目標類
                public class PersonDaoImpl extends HibernateUtil implements PersonDao {
                    @Override
                    public void savePerson(Person person) {
                        sessionFactory.getCurrentSession().save(person);
                    }
                }
                
                // 切面
                public class MyTransaction extends HibernateUtil{
                    private Transaction transaction;
                    // 通知
                    public void beginTransaction(){
                        this.transaction = sessionFactory.getCurrentSession().beginTransaction();      
                    }
                    // 通知
                    public void commit(){
                        this.transaction.commit();
                    }
                }
                
                配置檔案:
                    <!-- AOP   匯入目標類,匯入切面 -->
                    <bean id="personDao" class="cn.itcast.spring.aop.PersonDaoImpl"></bean>
                    <bean id="myTransaction" class="cn.itcast.spring.aop.MyTransaction"></bean>
                    <!-- AOP 的配置 -->
                    <aop:config>
                      <!-- 切入點表示式 裡面含有目標方法   -->
                      <aop:pointcut expression="execution(* cn.itcast.spring.aop.PersonDaoImpl.*(..))" id="perform"/>
                      <!-- 宣告切面 -->
                      <aop:aspect ref="myTransaction">
                        <!-- 宣告通知及其觸發時間 -->
                        <aop:before method="beginTransaction" pointcut-ref="perform"/>
                        <aop:after-returning method="commit" pointcut-ref="perform"/>
                      </aop:aspect>
                    </aop:config>
                    
                測試:
                    public class PersonTest {
                      @Test
                      public void test(){
                          ApplicationContext context = new ClassPathXmlApplicationContext(
                                              "cn/itcast/spring/aop/applicationContext.xml");  
                          // 注: 此處得到的是代理物件                                         
                          PersonDao personDao = (PersonDao) context.getBean("personDao");
                          Person person = new Person();
                          person.setPname("aaa");
                          person.setPsex("男");
                          personDao.savePerson(person);
                      }
                    }


            --------------------------------------------------------------------------------
            
         例1: 多個切面
            --------------------------------------------------------------------------------
                目標類:
                    public class SalaryManagerImpl {
                        public void show(){
                            System.out.println("目標方法:檢視工資");
                        }
                    }
                
                切面1:
                    public class Logger {
                        public void logger(){
                            System.out.println("logger");  
                        }
                    }
                
                切面2:    
                    public class Security {
                        public void security(){
                            System.out.println("security");
                        }
                    }
                    
                切面3:
                    public class Privilege {
                        private String access;
                        // set/get屬性
                        
                        public void hasAccess(ProceedingJoinPoint joinPoint) throws Throwable{
                            if(this.access.equals("admin")){
                                joinPoint.proceed();
                            }else{
                                System.out.println("對不起,您沒有許可權");
                            }
                        }
                    }
                
                配置檔案:
                    <bean id="salaryManager" class="cn.itcast.spring.aop.aspeces.SalaryManagerImpl"></bean>

                    <bean id="logger" class="cn.itcast.spring.aop.aspeces.Logger"></bean>
                    <bean id="security" class="cn.itcast.spring.aop.aspeces.Security"></bean>
                    <bean id="privilege" class="cn.itcast.spring.aop.aspeces.Privilege">
                        <property name="access" value="admin1"></property>
                    </bean>
                    
                    <aop:config>
                      <aop:pointcut expression="execution(
                                      * cn.itcast.spring.aop.aspeces.SalaryManagerImpl.*(..))" id="perform"/>
                      <aop:aspect ref="logger">
                          <aop:before method="logger" pointcut-ref="perform"/>
                      </aop:aspect>
                      <aop:aspect ref="security">
                          <aop:before method="security" pointcut-ref="perform"/>
                      </aop:aspect>
                      <aop:aspect ref="privilege">
                          <aop:around method="hasAccess" pointcut-ref="perform"/>
                      </aop:aspect>
                    </aop:config>
                
                測試:
                    public class SalaryTest {
                      @Test
                      public void test(){
                        ApplicationContext context = new ClassPathXmlApplicationContext("
                                          cn/itcast/spring/aop/aspeces/applicationContext.xml");          
                        SalaryManagerImpl proxy = (SalaryManagerImpl) context.getBean("salaryManager");
                        proxy.show();
                      }
                    }
            
            --------------------------------------------------------------------------------
       
       
        
      8、例:統一的錯誤異常處理
            --------------------------------------------------------------------------------
                public class PersonAction {
                    private PersonService personService = new PersonServiceImpl();
                    // set/get屬性    
                    public String savePerson() throws Exception{
                        this.personService.savePerson();
                        return null;
                    }            
                }
                
                public interface PersonService {
                    public void savePerson() throws Exception;
                }
                
                public class PersonServiceImpl implements PersonService {
                    PersonDao personDao = new PersonDaoImpl();                    
                    // set/get屬性
                    @Override
                    public void savePerson() throws Exception {
                      this.personDao.savePerson();
                      throw new RuntimeException("service層異常");    
                    }  
                }
                
                public interface PersonDao {
                    public void savePerson() throws Exception; 
                }
                
                public class PersonDaoImpl implements PersonDao {
                    @Override
                    public void savePerson() throws Exception{
                        System.out.println("save person daoImpl");
                        throw new RuntimeException("dao層異常");
                    }
                }          
                
                public class MyException {
                    public void myException(Throwable ex){
                        System.out.println(ex.getMessage());
                    }
                }
                
                配置檔案:
                    <bean id="personDao" class="cn.itcast.dao.impl.PersonDaoImpl"></bean>
                    <bean id="personService" class="cn.itcast.service.impl.PersonServiceImpl">
                      <property name="personDao">
                        <ref bean="personDao"/>
                      </property>
                    </bean>
                    <bean id="personAction" class="cn.itcast.action.PersonAction">
                      <property name="personService">
                        <ref bean="personService"/>
                      </property>
                    </bean>
                    <bean id="myException" class="cn.itcast.myException.MyException"></bean>                    
                    
                    <aop:config>
                      <aop:pointcut expression="execution(* cn.itcast.service.impl.*.*(..))" id="perform"/>
                      <aop:aspect ref="myException">
                        <aop:after-throwing method="myException" pointcut-ref="perform" throwing="ex"/>
                      </aop:aspect>
                    </aop:config>

                測試:
                    public class UnionExceptionTest {
                        @Test
                        public void test() throws Exception {
                            ApplicationContext context = new ClassPathXmlApplicationContext("
                                                                applicationContext.xml");
                            PersonAction personAction = (PersonAction) context.getBean("personAction");
                            personAction.savePerson();
                        }                     
                    }
                
            --------------------------------------------------------------------------------
       
       
      9、 springAOP註解的形式
            --------------------------------------------------------------------------------
                public class Person implements Serializable {
                    private Long pid;
                    private String pname;
                    private String psex;
                    // set/get屬性
                }
            
                public interface PersonDao {
                    public void savePerson(Person person);
                }
                
                @Repository("personDao")
                public class PersonDaoImpl extends HibernateUtil implements PersonDao {
                    @Override
                    public void savePerson(Person person) {
                        sessionFactory.getCurrentSession().save(person);
                    }
                }
                
                /**
                @Aspect相當於:
                  <aop:config></aop:config>
                */
                // 切面
                @Component("myTransaction")
                @Aspect
                public class MyTransaction extends HibernateUtil{
                    private Transaction transaction;
                    
                    /**
                    @Pointcut("execution(* cn.itcast.spring.aop.annotation.PersonDaoImpl.*(..))")相當於
                      <aop:pointcut expression="execution(* cn.itcast.spring.aop.annotation.PersonDaoImpl.*(..))" id="perform"/>            
                     */
                    @Pointcut("execution(* cn.itcast.spring.aop.annotation.PersonDaoImpl.*(..))")
                    private void perform(){}  // 方法簽名,返回值必須是void,並且方法的修飾符最好是private
                    
                    // 前置通知  
                    /**
                    @Before("perform()")相當於:
                      <aop:before method="beginTransaction" pointcut-ref="perform"/>
                     */
                    @Before("perform()")
                    public void beginTransaction(){
                      this.transaction = sessionFactory.getCurrentSession().beginTransaction();      
                    }
                    
                    // 後置通知  
                    /**
                    @AfterReturning(value="perform()",returning="var")相當於:
                      <aop:after-returning method="commit" pointcut-ref="perform" returning="var"/>
                     */
                    @AfterReturning(value="perform()",returning="var")
                    public void commit(Object var){
                      this.transaction.commit();
                    }
                }
                
                配置檔案:
                    <!-- 
                      把目標類和切面納入到spring容器中管理,啟動類掃描機制
                    -->
                    <context:component-scan base-package="cn.itcast.spring.aop.annotation"/>
                    
                    <!-- 啟動AOP的註解解析器  然後再在切面中寫註解來代替配置資訊  -->
                    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
                
                測試:
                    public class PersonTest {
                        @Test
                        public void test(){
                              ApplicationContext context = new ClassPathXmlApplicationContext("
                                      cn/itcast/spring/aop/annotation/applicationContext.xml");                       
                              PersonDao personDao = (PersonDao) context.getBean("personDao");
                              Person person = new Person();
                              person.setPname("bbb");
                              person.setPsex("男");
                              personDao.savePerson(person);
                        }
                    }
                
            --------------------------------------------------------------------------------
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       

相關推薦

spring03 AOP各種通知/切面例子

一、 springAOP        1、作用: 使得事務、日誌、安全性框架、許可權、目標方法之間完全是鬆耦合的                2、組成               1、切面:   事務、日誌、安全性框架、許可權等都是切面               2

java學習筆記——spring之aop切面類中五種通知的使用存在切面類時切面通知的執行順序註釋的方式定義切面類與通知xml配置的方式定義切面類與通知

3、AOP AOP:(Aspect Oriented Programming)面向切面程式設計; OOP:(Object Oriented Programming )面向物件程式設計; 面向切面程式設計:基於OOP基礎之上新的程式設計思想; 指在程式執行期間,

Spring入門知識 ———— 實現AOP返回通知異常通知環繞通知

一、引言 以你為AOP只有前置通知和後置通知嗎? 那你就錯啦 在AOP中一共有五種方式: @Befor:前置通知:在方法執行之前執行 @After:後置通知,在方法之後執行 @AfterRet

Spring 學習(十七)——Spring AOP之返回通知異常通知和環繞通知

返回通知 •無論連線點是正常返回還是丟擲異常, 後置通知都會執行. 如果只想在連線點返回的時候記錄日誌, 應使用返回通知代替後置通知.   在返回通知中訪問連線點的返回值 •在返回通知中, 只要將 returning 屬性新增到 @AfterReturning 註解中

Spring aop 前置通知後置通知返回通知 異常通知 後置通知

  Spring AOP定義切面 Ⅰ 首先介紹一下寫Spring Aop思路  一、首先在專案中加入aop所需要的jar aopalliance-1.0.jar aspectjweaver-1.6.11.jar commons-logging-1.1.1.jar sprin

Spring4筆記----AOP的環繞通知切面的優先順序以及重用切入點定義

一、環繞通知 環繞通知是所有通知型別中功能最為強大的, 能夠全面地控制連線點. 甚至可以控制是否執行連線點. 對於環繞通知來說, 連線點的引數型別必須是 ProceedingJoinPoint . 它是 JoinPoint 的子介面, 允許控制何時執行, 是否執行連線點.

AOP基礎:繼承接口方式實現:前置通知後置通知異常通知環繞通知 (demo)

widget pointcut 1.0 add contex 分享圖片 lns stat ado 運行環境:     ide: Spring Tool Suite 3 Version: 3.9.8.RELEASE     jdk:   1.8     系統:  

IE6IE7IE8及其他瀏覽器元素並排顯示

wid 輸入框 -s tro 自身 out outline size mar IE6、IE7、IE8及其他瀏覽器多個元素並排顯示 HTML代碼 <div class="line"> <h1>全部input框</h1>

56彈出框和視窗之間的切換

學習目標: 1、掌握使用Swing實現彈出框功能 2、使用Swing切換視窗 3、新視窗的定義和彈出   學習過程: 一、彈出框 1、簡介 Java 中的對話方塊是一個容器,它充當父容器的子容器  Swing中的彈出式對話方塊是用JOptionPa

用java來實現接收感測器裡面的溫溼度各種氣體大氣壓

之前主要依靠公司裡面一個同事用vb編的程式,因為我不知道crc校驗是怎麼出來的,為了趕專案用了vb,然後用java 呼叫資料庫裡面的資料;但是一個專案應該統一語言的; 我需要接受如下感測器資訊 感測器(-130米主通風井) 192.168.1

AOP 為目標方法織入通知

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSc

[Xcode10 實際操作]九實用進階-(23)Storyboard故事板中的頁面跳轉

本文將演示多個Storyboard故事板中的頁面跳轉。 使用快捷鍵【Command】+【N】建立一個新的故事板檔案。 (在專案資料夾【DemoApp】上點選滑鼠右鍵【New File】建立) ->【Storyboard】->【Next】->【Save As】:Storyboard.st

1Jquery form表單ajax提交 2jquery.filter校驗相同型別的文字框是否輸入資料有重複

JSP引用該JS <script type="text/javascript" src="http://malsup.github.com/jquery.form.js"></script> 表單儲存按鈕 onclick=save(); func

@resource@Autowired@Service在一個介面實現類中的應用

      Spring在沒有引入註解之前,傳統的Spring做法是使用.xml檔案來對bean進行注入,所有的內容都需要配置在.xml檔案中,使配置和程式設計分離,卻增加了可讀性和複雜度。        Spring註解將複雜的配置檔案用簡單@xxx代替,當出現一個介

Django專案中包含應用時對url的配置

一個Django工程中多數情況下會存在多個應用, 如何針對多個應用的url進行配置呢,有以下兩種方案: 1、在Django工程的urls.py中針對每個應用分別配置不同的url路徑 2、在工程總體的urls.py中引入每個應用的url配置檔案,不

Notification(Notification的通知欄常駐各種樣式點選無效禁止滑動刪除相容低版本)

Notification(Notification的通知欄常駐、Notification的各種樣式、Notification點選無效、Notification禁止滑動刪除) Android的Notification是android系統中很重要的一個機制, 產品人員常常利用通

《Spring AOP》-----各種通知解析

前言 上一篇文章中,小編簡單介紹了SpringAop中的一些概念,意義、還有簡單入門的小例子,那麼現在小編帶著讀者解析一下SpringAop中的幾種通知,所謂的通知,就是切面中的幾種方法。

Spring AOP-通知-為目標方法織入切面

AOP-通知-為目標方法織入多個切面 開發中可能會遇到為目標方法織入多個切面,比如前置。後置通知都需要 介面 package com.hk.spring.aop06; public interface SomeService { publi

java程式碼實現CSV檔案讀取將資料拆分成CSV檔案及資料匯出到CSV檔案

package com.cn; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; impor

返回通知異常通知環繞通知

pro 動態 正常 消失 ret point 動態代理 throw com 返回通知:是在方法正常結束之後執行的通知,可以訪問方法返回值。 使用@AfterReturning註釋,我們還可以在註釋裏面指定一個返回值的名字,然後再方法中使用它。