天天看點

Spring-AOP 通過配置檔案實作 前置增強概述在Spring中配置

  • 概述
  • 在Spring中配置
    • 通過配置檔案實作增強
      • 配置檔案
      • ProxyFactory Bean配置檔案當中常用的屬性
      • 測試類
    • 其他代碼

概述

在上篇博文的案例中

Spring-AOP 建立增強類-前置增強

我們使用org.springframework.aop.framework.ProxyFactory通過編碼的方式将GreetingBeforeAdvice的增強織入目标類NaiveWaiter中

結合我們前面說的

Java-JDK動态代理

Java-CGLib動态代理

動态代理技術是不是很相似?

我們看下的源碼 ProxyFactoryBean#setProxyInterfaces

Spring-AOP 通過配置檔案實作 前置增強概述在Spring中配置

可以發現,ProxyFactoryBean的内部其實就是使用JDK或者CGLib動态代理技術将增強應用到目标類中的。

Spring定義的AOPProxy類具有兩個final類型的實作類,如下圖所示

Spring-AOP 通過配置檔案實作 前置增強概述在Spring中配置
  • Cglib2AopProxy是使用cglib代理技術來建立代理
  • JdkDynamicAopProxy是使用jdk代理技術來建立代理

如果通過ProxyFactory的setInterfaces(Class[] interfaces)方法指定目标接口進行代理,則ProxyFactory使用JdkDynamaicAopProxy,如果針對類的代理,則使用Cglib2AopProxy.

此外,還可以通過ProxyFactory的setOptimize(true)方法讓ProxyFactory啟動優化代理方式,這樣,針對接口的代理也會使用Cglib2AopProxy。

我們使用JDK代理來實作 Spring-AOP 增強(Advice)類型和建立增強類 中的業務測試類

//建立代理工廠對象
ProxyFactory factory=new ProxyFactory();
//設定代理接口
factory.setInterfaces(target.getClass().getInterfaces());
//設定代理類
factory.setTarget(target);
//設定增強類
factory.addAdvice(advice);           

複制

使用CGLib代理實作則為:

ProxyFactory factory=new ProxyFactory();
//設定代理接口
factory.setInterfaces(target.getClass().getInterfaces());
//啟用優化,将啟用cglib代理方式
factory.setOptimize(true);
//設定代理類
factory.setTarget(target);
//添加增強類
factory.addAdvice(advice);           

複制

ProxyFactory通過addAdvice來增加一個增強。 使用者可以使用該方法增加多個增強,通過增強形成一個增強鍊,他們的調用順序和添加順序是一緻的

在Spring中配置

代碼已托管到Github—> https://github.com/yangshangwei/SpringMaster

通過配置檔案實作增強

Spring-AOP 通過配置檔案實作 前置增強概述在Spring中配置

配置檔案

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="target" class="com.xgj.aop.spring.advice.proxyFactory.NaiveWaiter"/>

    <bean id="greetingBeforeAdvice" class="com.xgj.aop.spring.advice.proxyFactory.GreetingBeforeAdvice"/>

    <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"
        p:proxyInterfaces="com.xgj.aop.spring.advice.proxyFactory.Waiter"
        p:interceptorNames="greetingBeforeAdvice"
        p:target-ref="target"/>

beans>           

複制

ProxyFactory Bean配置檔案當中常用的屬性

  • target:我們需要代理的目标對象
  • proxyInterfaces:代理所要實作的接口,可以是多個接口
  • interceptorNames:需要織入的目标對象的Bean的清單(增強類的Bean清單),使用Bean的名稱來指定。
  • singleton:确定傳回的代理是不是單執行個體的,系統預設傳回的是單執行個體的。
  • optimize:當值為true時,強制使用cglib代理。當是singleton的執行個體時我們推薦使用cglib代理,當是其他作用域的時候,推薦使用JDK的代理。原因是cglib建立代理速度比較慢,但是運作效率高。JDK代理則剛好相反。
  • proxyTargetClass:是否對類進行代理而不是對接口進行代理,當值為true的時候使用cglib代理

将proxyTargetClass設定為true後,無需再設定proxyInterfaces屬性,即使設定了也會被ProxyFactory忽略

測試類

package com.xgj.aop.spring.advice.proxyFactory;

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

public class BeforceAdivceByXmlTest {

    @Test
    public void test() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "classpath:com/xgj/aop/spring/advice/proxyFactory/beans.xml");

        Waiter waiter = ctx.getBean("waiter", Waiter.class);
        waiter.greetTo("Xiao");
        waiter.serverTo("GongJiang");
    }
}           

複制

運作單元測試:

Spring-AOP 通過配置檔案實作 前置增強概述在Spring中配置

其他代碼

業務接口類:Waiter.Java

業務實作類:NativeWaiter.java

業務增強類:GreetingBeforeAdvice.java

參考 Spring-AOP 增強(Advice)類型和建立增強類#執行個體-通過代碼實作增強