1. 程式人生 > >Spring AOP之ProxyFactoryBean與BeanNameAutoProxyCreator

Spring AOP之ProxyFactoryBean與BeanNameAutoProxyCreator

準備業務介面和實現類

package org.lanqiao.springDemo.aop;

public interface SomeBiz {
  public void addBiz();
  public void other();
}
package org.lanqiao.springDemo.aop;

public class SomeBizImpl implements SomeBiz{
  public void addBiz(){
    System.out.println("新增資料的業務邏輯");
  }
  public void other(){
    System.out.println("其他方法"
); } }

編寫方法攔截器(通知)

package org.lanqiao.springDemo.aop;

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

public class Advice1 implements MethodInterceptor {
  public Object invoke(MethodInvocation methodInvocation) throws Throwable {
    System.out.printf("代理邏輯發生在呼叫方法%s之前\n"
, methodInvocation.getMethod().toGenericString()); return methodInvocation.proceed(); } }

ProxyFactoryBean基本配置

<!--通知-->
  <bean id="advice1" class="org.lanqiao.springDemo.aop.Advice1" />

  <!--切面組合-->
  <bean class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"
id="advisor1">
<property name="advice" ref="advice1"/> <!--這裡不是正則表示式而是簡單的通配--> <property name="mappedName" value="*Biz"/> </bean> <bean id="someBiz" class="org.lanqiao.springDemo.aop.SomeBizImpl"/> <!--宣告代理--> <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="someBizProxy"> <!--指定介面--> <property name="proxyInterfaces" value="org.lanqiao.springDemo.aop.SomeBiz"/> <!--指定實現類--> <property name="target" ref="someBiz"/> <!--攔截器名字--> <property name="interceptorNames"> <list> <value>advisor1</value> </list> </property> </bean>

測試

package org.lanqiao.springDemo.aop;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;

@ContextConfiguration("classpath:aop.xml")
public class SomeBizImplTest extends AbstractJUnit4SpringContextTests {
  @Autowired
  private SomeBiz someBizProxy;

  @org.junit.Test
  public void addBizUsingInterfaceProxy() throws Exception {
    someBizProxy.addBiz();
  }
}

結果:

代理邏輯發生在呼叫方法public abstract void org.lanqiao.springDemo.aop.SomeBiz.addBiz()之前
新增資料的業務邏輯

使用更強大的正則切入點

使用JdkRegexpMethodPointcut

<!--通知-->
  <bean id="advice1" class="org.lanqiao.springDemo.aop.Advice1" />


<bean id="regexpAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
  <property name="advice" ref="advice1"/>
  <property name="pointcut">
    <bean class="org.springframework.aop.support.JdkRegexpMethodPointcut">
      <!--這裡可以使用正則表示式-->
      <property name="pattern" value=".*Biz.*" />
    </bean>
  </property>
</bean>

  <bean id="someBiz" class="org.lanqiao.springDemo.aop.SomeBizImpl"/>

  <!--宣告代理-->
  <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="someBizProxy">
    <!--指定介面-->
    <property name="proxyInterfaces" value="org.lanqiao.springDemo.aop.SomeBiz"/>
    <!--指定實現類-->
    <property name="target" ref="someBiz"/>
    <!--攔截器名字-->
    <property name="interceptorNames">
      <list>
        <value>regexpAdvisor</value>
      </list>
    </property>
  </bean>

測試效果同上

使用更強大的可以通配beanName的BeanNameAutoProxyCreator

上例的缺點在於,對於每個業務類我們都要配一個ProxyFactoryBean,接下來我們使用更為強大的BeanNameAutoProxyCreator來自動為滿足通配條件的bean生產代理,而且在依賴業務類的地方直接使用原始beanName即可:

<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <!--攔截器名字-->
    <property name="interceptorNames">
      <list>
        <value>regexpAdvisor</value>
      </list>
    </property>
    <!--bean的名字可以用萬用字元-->
    <property name="beanNames" value="*Biz"/>
  </bean>

這樣配置後,我們不需要ProxyFactoryBean,依賴業務bean時,也直接依賴原始bean的名字:

@Autowired
  private SomeBiz someBiz;

  @org.junit.Test
  public void addBizUsingBean() throws Exception {
    someBiz.addBiz();
  }

還有更強大的AspectJExpressionPointcutAdvisor

其他配置都不要,配置如下

<!--通知-->
  <bean id="advice1" class="org.lanqiao.springDemo.aop.Advice1" />
  <!--業務bean-->
  <bean id="someBiz" class="org.lanqiao.springDemo.aop.SomeBizImpl"/>

  <bean id="aspectAdvisor" class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">
    <property name="advice" ref="advice1"/>
    <!--切入點表示式-->
    <property name="expression" value="execution( * org.lanqiao.springDemo..*Biz*.*Biz(..))" />
  </bean>
  <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

因為我們的表示式可以直接指定包名、類名、方法名甚至引數型別、返回值型別等,所以不再需要基於bean名稱的代理,必須開啟自動代理:DefaultAdvisorAutoProxyCreator

希望有幫助,轉載無需授權!