Spring AOP之ProxyFactoryBean与BeanNameAutoProxyCreator

来源:互联网 发布:linux文件目录介绍 编辑:程序博客网 时间:2024/06/06 02:19

准备业务接口和实现类

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

希望有帮助,转载无需授权!

阅读全文
0 0
原创粉丝点击