20_AOP_Advice增強1(前置、后置、環繞)


【增強的類型】

1.前置增強org.springframework.aop.BeforeAdvice

由於Spring只支持方法級別的增強,所以MethodBeforeAdvice是目前可用的前置增強,表示在目標方法執行前執行前置增強,BeforeAdvice是為了將來版本擴展需要而定義的。

2.后置增強org.springframework.aop.AfterReturningAdvice

表示在目標方法執行后執行增強。

3.環繞增強org.aopalliance.intercept.MethodInterceptor

表示在目標方法執行前后執行增強。

4.異常拋出增強org.springframework.aop.ThrowsAdvice

表示在目標方法拋出異常時執行增強。

5.引介增強org.springframework.aop.IntroductionInterceptor

在目標類中添加一些新的屬性和方法。

 

【前置、后置、環繞增強整個工程】

【車子接口 Car.java】

package com.Higgin.part1;

/**
 * 車子接口
 */
public interface Car {
    public void drive();
}

【具體奔馳車類:BenzCar.java】

package com.Higgin.part1;

/**
 * 奔馳車類
 * 我們希望測試奔馳車在執行drive()方法前、后、前后增強的情況
 */
public class BenzCar implements Car{

    @Override
    public void drive() {
        System.out.println("【業務方法】奔馳車在行駛....");
    }

}

【前置增強類】

package com.Higgin.part1;

import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;

/**
 * 前置增強類
 * 實現的是:MethodBeforeAdvice接口
 */
public class DriveBeforeAdvice implements MethodBeforeAdvice{

    /**
     * method:目標類的方法
     *   args:目標類方法的參數
     *    obj:目標類的實例
     */
    @Override
    public void before(Method method, Object[] args, Object obj)throws Throwable {
        System.out.println("【前置增強】開車前自動放音樂~~~");
    }
}

【測試前置增強類1:TestBeforeAdvice】

package com.Higgin.part1.Test;

import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;
import com.Higgin.part1.BenzCar;
import com.Higgin.part1.Car;
import com.Higgin.part1.DriveBeforeAdvice;

/**
 * 測試 前置增強
 */
public class TestBeforeAdvice{
    public static void main(String[] args) {
        Car benz=new BenzCar();        //目標對象
        BeforeAdvice driveBeforeAdvice=new DriveBeforeAdvice(); //前置增強
        
        ProxyFactory pf=new ProxyFactory();  //1.Spring代理工廠
        
        pf.setTarget(benz);                  //2.設置代理目標對象
        
        pf.addAdvice(driveBeforeAdvice);     //3.為代理對象添加增強
        
        Car carProxy=(Car) pf.getProxy();    //4.生成代理實例
        
        carProxy.drive();
        
    }
}

[ 運行結果 ]

【測試前置增強類2:用Spring的xml配置文件方式:TestBeforeAdviceXml.java】

package com.Higgin.part1.Test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.Higgin.part1.Car;

public class TestBeforeAdviceXml {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("part1.xml");
        Car car=(Car) context.getBean("benzCar1");
        car.drive();
    }
}

【測試前置增強類2:用Spring的xml配置文件方式的配置文件:part1.xml】

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"  
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
    xmlns:cache="http://www.springframework.org/schema/cache"  
    xsi:schemaLocation="  
    http://www.springframework.org/schema/context  
    http://www.springframework.org/schema/context/spring-context.xsd  
    http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans.xsd  
    http://www.springframework.org/schema/tx  
    http://www.springframework.org/schema/tx/spring-tx.xsd  
    http://www.springframework.org/schema/jdbc  
    http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd  
    http://www.springframework.org/schema/cache  
    http://www.springframework.org/schema/cache/spring-cache-3.1.xsd  
    http://www.springframework.org/schema/aop  
    http://www.springframework.org/schema/aop/spring-aop.xsd  
    http://www.springframework.org/schema/util  
    http://www.springframework.org/schema/util/spring-util.xsd">
    
    <!-- 要增強的目標對象 -->
    <bean id="target" class="com.Higgin.part1.BenzCar"/>
    
    <!-- 前置增強的類 -->
    <bean id="driveBeforeAdvice" class="com.Higgin.part1.DriveBeforeAdvice" />
 
    <!-- Spring代理工廠的成員變量配置(前置增強)-->
    <bean id="benzCar1" class="org.springframework.aop.framework.ProxyFactoryBean"
        p:proxyInterfaces="com.Higgin.part1.Car" 
        p:interceptorNames="driveBeforeAdvice"
        p:target-ref="target"
    />
      
</beans>

[ 運行結果 ]

 

 【后置增強類:DriveAfterAdvice.java】

package com.Higgin.part1;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

/**
 * 后置增強類
 * 實現的是:AfterReturningAdvice
 */
public class DriveAfterAdvice implements AfterReturningAdvice{

    @Override
    public void afterReturning(Object returnObj, Method method, Object[] args, Object obj) throws Throwable {
        System.out.println("【后置增強】停車后自動關閉音樂~~~");
    }
}

【測試后置增強類1:TestAfterAdvice.java】

package com.Higgin.part1.Test;

import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;

import com.Higgin.part1.BenzCar;
import com.Higgin.part1.Car;
import com.Higgin.part1.DriveAfterAdvice;
import com.Higgin.part1.DriveBeforeAdvice;

public class TestAfterAdvice {
    public static void main(String[] args) {
        Car benz=new BenzCar();        //目標對象
        BeforeAdvice driveBeforeAdvice=new DriveBeforeAdvice();         //前置增強
        AfterReturningAdvice driveAfterAdvice=new DriveAfterAdvice();  //后置增強
        
        ProxyFactory pf=new ProxyFactory();  //1.Spring代理工廠
        
        pf.setTarget(benz);                  //2.設置代理目標
        
        pf.addAdvice(driveBeforeAdvice);     //3.為代理對象添加 前 置增強
        pf.addAdvice(driveAfterAdvice);      //3.為代理對象添加 后 置增強
        
        Car carProxy=(Car) pf.getProxy();    //4.生成代理實例
        
        carProxy.drive();
    }
}

【運行結果】

【測試后置增強類2:用Spring的xml配置文件方式:TestAfterAdviceXml.java】

package com.Higgin.part1.Test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.Higgin.part1.Car;

public class TestAfterAdviceXml {
    public static void main(String[] args) {
        ApplicationContext context =new  ClassPathXmlApplicationContext("part1.xml");
        Car benz=(Car) context.getBean("benzCar2");
        benz.drive();
    }
}

【測試后置增強類2:用Spring的xml配置文件方式的配置文件:part1.xml】

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"  
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
    xmlns:cache="http://www.springframework.org/schema/cache"  
    xsi:schemaLocation="  
    http://www.springframework.org/schema/context  
    http://www.springframework.org/schema/context/spring-context.xsd  
    http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans.xsd  
    http://www.springframework.org/schema/tx  
    http://www.springframework.org/schema/tx/spring-tx.xsd  
    http://www.springframework.org/schema/jdbc  
    http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd  
    http://www.springframework.org/schema/cache  
    http://www.springframework.org/schema/cache/spring-cache-3.1.xsd  
    http://www.springframework.org/schema/aop  
    http://www.springframework.org/schema/aop/spring-aop.xsd  
    http://www.springframework.org/schema/util  
    http://www.springframework.org/schema/util/spring-util.xsd">
    
    <!-- 要增強的目標對象 -->
    <bean id="target" class="com.Higgin.part1.BenzCar"/>
    
    <!-- 前置增強的類 -->
    <bean id="driveBeforeAdvice" class="com.Higgin.part1.DriveBeforeAdvice" />
    <!-- 后置增強的類 -->
    <bean id="dirveAfterAdvice" class="com.Higgin.part1.DriveAfterAdvice" />

    <!-- Spring代理工廠的成員變量配置(后置增強+前置增強) -->
    <bean id="benzCar2" class="org.springframework.aop.framework.ProxyFactoryBean"
        p:proxyInterfaces="com.Higgin.part1.Car" 
        p:interceptorNames="driveBeforeAdvice,dirveAfterAdvice"
        p:target-ref="target"
    />
    
</beans>

[ 運行結果 ]

 

【環繞增強類:DriveAroundAdvice.java】

package com.Higgin.part1;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

/**
 * 環繞增強
 * 實現的接口:MethodInterceptor
 * 注意:需要導入jar包:aopalliance-1.0.jar
 */
public class DriveAroundAdvice implements MethodInterceptor{

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("【前置增強】開車前自動打開音樂~~~");
        Object obj=invocation.proceed();  //通過反射執行目標的業務方法
        System.out.println("【后置增強】停車后自動關閉音樂~~~");
        return obj;
    }

}

【環繞增強測試類1:TestAroundAdvice.java】

package com.Higgin.part1.Test;

import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.framework.ProxyFactory;

import com.Higgin.part1.BenzCar;
import com.Higgin.part1.Car;
import com.Higgin.part1.DriveAroundAdvice;

public class TestAroundAdvice {
    public static void main(String[] args) {
        Car benzCar=new BenzCar();
        MethodInterceptor driveAroundAdvice=new DriveAroundAdvice();
        
        ProxyFactory pf=new ProxyFactory();
        
        pf.setTarget(benzCar);
        
        pf.addAdvice(driveAroundAdvice);
        
        Car carProxy=(Car) pf.getProxy();
        
        carProxy.drive();
    }
}

[ 運行結果 ]

【測試環繞增強類2:用Spring的xml配置文件方式:TestAroundAdviceXml.java】

package com.Higgin.part1.Test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.Higgin.part1.Car;

public class TestAroundAdviceXml {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("part1.xml");
        Car car=(Car) context.getBean("benzCar3");
        car.drive();
    }
}

【測試環繞增強類2:用Spring的xml配置文件方式的配置文件:part1.xml】

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"  
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
    xmlns:cache="http://www.springframework.org/schema/cache"  
    xsi:schemaLocation="  
    http://www.springframework.org/schema/context  
    http://www.springframework.org/schema/context/spring-context.xsd  
    http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans.xsd  
    http://www.springframework.org/schema/tx  
    http://www.springframework.org/schema/tx/spring-tx.xsd  
    http://www.springframework.org/schema/jdbc  
    http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd  
    http://www.springframework.org/schema/cache  
    http://www.springframework.org/schema/cache/spring-cache-3.1.xsd  
    http://www.springframework.org/schema/aop  
    http://www.springframework.org/schema/aop/spring-aop.xsd  
    http://www.springframework.org/schema/util  
    http://www.springframework.org/schema/util/spring-util.xsd">
    
    <!-- 要增強的目標對象 -->
    <bean id="target" class="com.Higgin.part1.BenzCar"/>
    
    <!-- 環繞增強的類 -->
    <bean id="driveAroundAdvice" class="com.Higgin.part1.DriveAroundAdvice"/>
 
    <!-- Spring代理工廠的成員變量配置(環繞增強) -->
    <bean id="benzCar3" class="org.springframework.aop.framework.ProxyFactoryBean"
        p:proxyInterfaces="com.Higgin.part1.Car" 
        p:interceptorNames="driveAroundAdvice"
        p:target-ref="target"
    />
   
</beans>

[ 運行結果 ]

 

 

【分析】

1.關於spring的xml配置文件的分析

其中的ProxyFactoryBean類是FactoryBean的實現類,

FactoryBean負責實例化一個Bean,

ProxyFactoryBean負責為其他Bean創建代理實例,它內部使用ProxyFactory來完成這一工作。

ProxyFactoryBean的幾個可配置屬性(成員變量)

  target:代理的目標對象

  proxyInterfaces:代理需要實現的接口,可以是多個接口。該屬性該有一個別名interfaces。

  interceptor:需要織入目標對象的Bean列表。采用Bean的名稱指定。這些Bean必須是實現了org.aoplliance.interceptor.MethodInterceptor或者org.springframework.Advisor的Bean,配置中的順序對應調用的順序。

  singleton:返回的代理是否是單例,默認單例。

  optimize:為true時,強制使用Cglib代理,對於Singleton的代理,建議使用CGlib。對於其他作用域類型的代理,最好使用JDK代理。(CGLib創建代理時速度慢,而創建出來的代理對象運行效率高,JDK代理相反)

  proxyTargetClass:是否對類進行代理(而不是對接口進行代理),設置為true時,使用CGLib代理。

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM