准备业务接口和实现类
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
希望有帮助,转载无需授权!