Spring AOP之ProxyFactoryBean與BeanNameAutoProxyCreator
阿新 • • 發佈:2019-01-10
準備業務介面和實現類
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
希望有幫助,轉載無需授權!