Spring AOP常用的实现方式有以下三种:
1.实现Spring API的传统方式
2.@AspectJ注解驱动的切面
3.基于XML设置的纯POJO切面
Spring支持五种类型的通知:
Before(前) org.apringframework.aop.MethodBeforeAdvice
After-returning(返回后) org.springframework.aop.AfterReturningAdvice
After-throwing(抛出后) org.springframework.aop.ThrowsAdvice
Arround(周围) org.aopaliance.intercept.MethodInterceptor
Introduction(引入) org.springframework.aop.IntroductionInterceptor
我们就以最常用的Before和After-returning为例,讲解以下这三种AOP的使用。
一.实现Spring API的传统方式
//接口
public interface IHello {
public void hello(String name);
}
//实现类
public class HelloSpeaker implements IHello {
public void hello(String name) {
System.out.println("Hello, "+name);
}
}
定义一个日志类,在hello执行前后打印日志
public class LogAdvice implements MethodBeforeAdvice, AfterReturningAdvice {
public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
System.out.println("print log afterReturning ");
}
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
System.out.println("print log before ");
}
}
Spring核心配置文件applicationContext.xml配置AOP
<bean id="helloSpeaker" class="com.zs.test.HelloSpeaker"/>
<bean id="logAdvice" class="com.zs.test.aopone.LogAdvice"/>
<bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.zs.test.IHello"></property>
<property name="target" ref="helloSpeaker"></property>
<property name="interceptorNames" value="logAdvice"></property>
</bean>
注:通过org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator可以简化xml配置。
测试类
public static void main( String[] args )
{
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
IHello helloProxy = (IHello)ctx.getBean("helloProxy");
helloProxy.hello("tom");
}
二.更简单的方式,通过AspectJ提供的注解实现AOP
将LogAdvice修改为LogAspect
@Aspect
public class LogAspect {
//@Pointcut("execution(* *.hello(..))")//Pointcut表达式
@Pointcut("execution(* com.zs.test.IHello.*(..))")//Pointcut表达式
public void helloPoint(){}//Pointcut签名
@Before("helloPoint()")
public void before(){
System.out.println("print log before ");
}
@AfterReturning("helloPoint()")
public void afterReturning(){
System.out.println("print log afterReturning ");
}
}
在上面的代码中定义了一个Pointcut,Pointcut的定义包括两部分:Pointcut表达式与Pointcut签名。在开发中可以将共用的一些Pointcut组织起来单独定义在一个类里面,供整个应用程序使用,使用时可以指定完整类名称加上Pointcut签名。
Spring配置文件applicationContext.xml中,使用<aop:aspectj-autoproxy/> 标签启用@Aspect的Annotation支持。
<bean id="helloSpeaker" class="com.zs.test.HelloSpeaker"/>
<bean id="logAspect" class="com.zs.test.aoptwo.LogAspect"/>
<aop:aspectj-autoproxy/>
测试类,注意这里直接获取的是helloSpeaker
public static void main( String[] args )
{
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
IHello helloSpeaker = (IHello)ctx.getBean("helloSpeaker");
helloSpeaker.hello("tom");
}
三.基于XML设置的纯POJO切面
这种方式的LogAdvice不必耦合任何API,只是一个纯的POJO
public class LogAdvice{
public void afterReturning() throws Throwable {
System.out.println("print log afterReturning ");
}
public void before() throws Throwable {
System.out.println("print log before ");
}
}
配置文件
<bean id="helloSpeaker" class="com.zs.test.HelloSpeaker"/>
<bean id="logAdvice" class="com.zs.test.aopthree.LogAdvice"/>
<aop:config>
<aop:aspect ref="logAdvice">
<aop:before method="before" pointcut="execution(* *.hello(..))" />
<aop:after method="afterReturning" pointcut="execution(* *.hello(..))" />
</aop:aspect>
</aop:config>
另一种写法
<aop:config>
<aop:aspect ref="logAdvice">
<aop:pointcut id="helloPoint" expression="execution(* *.hello(..))" />
<aop:before method="before" pointcut-ref="helloPoint" />
<aop:after method="afterReturning" pointcut-ref="helloPoint" />
</aop:aspect>
</aop:config>
测试类,与上一个例子完全一样
public static void main( String[] args )
{
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
IHello helloSpeaker = (IHello)ctx.getBean("helloSpeaker");
helloSpeaker.hello("tom");
}
不知不觉已到了2018年最后一个 月了,不知道年底前还能再做点什么?