Spring之AOP模块

n672 9年前

AOP(AspectOriented Programming,面向切面编程)是Spring框架的一个重要特征

Spring推荐使用接口编程

Spring提供三种拦截器:方法前拦截器、返回后拦截器、异常抛出拦截器

 

拦截器定义

//Service接口  public interface IAopService{        public void withAop() throws Exception;                    //将会被拦截        public void withoutAop() throws Exception;        //不会被拦截  }     public class AopServiceImpl implements IAopService{        private String name;        public void withAop() throws Exception{               System.out.println("有AOP的函数运行。name:"+name);               if(name.trim().length() == 0){                      throw new AccountException("name属性不能为空");               }        }           public void withoutAop() throws Exception{                      System.out.println("没有AOP的函数运行。");        }           public void setName(String name){               this.name = name;        }           public String getName(){               return this.name;        }  }

//方法前拦截器,检查name是否为空  import  org.springframework.aop.MethodBeforeAdvice  public class MethodBeforeInterceptor implements MethodBeforeAdvice{        //调用对象的方法前执行该方法        //参数分别为被调用的方法、被调用方法的参数、对象        publicvoid before(Method method,Object [] args,Object instance) throws Throwable{               System.out.println("即将执行方法:"+method.getName());               //               if(instance instanceof AopServiceImpl){                      String name = ((AopServiceImpl)instance).getName();                      if(name == null){                             throw new NullPointerException("name不能为空");                      }               }        }                }     //返回后拦截器  import  org.springframework.aop.AfterReturningAdvice  public class MethodAfterInteceptor implements AfterReturningAdvice{        //参数分别为方法返回值、被调用方法、方法参数、被拦截的对象        publicvoid afterReturning(Object value,Method method,Object [] args,Object instance) throwsThrowable{                             System.out.println("方法:"+method.getName()+"执行完毕,返回值为:"+value);        }         }     //异常拦截器捕获异常  import  org.springframework.aop.ThrowAdvice  public class ThrowsInterceptor implements ThrowAdvice{        //参数分别为被调用的方法、方法参数、对象实例、抛出的异常        //前三个参数可以省略,第四个参数是必须的,这样设计是为了使开发者灵活地定义多个方法捕获各种不同的异常        publicvoid afterThrowing(Method method,Object [] args,Object instance,AccountExceptionex) throws Throwable {               System.out.println("方法:"+method.getName()+"抛出了异常:"+ex);        }           publicvoid afterThrowing(NullPointerException ex) throws Throwable {               System.out.println("抛出了异常:"+ex);        }     }

拦截器配置

Spring无法将Service的实现类与拦截器直接组装,因为没有对应的setter、getter方法。安装时借助的是Spring的代理类,把拦截器安装到NameMatchMethodPointcutAdvisor中,把自动以的Service安装到ProxyFactoryBean中,然后组装到一块

<!--方法前拦截器MethodBeforeInterceptor安装到NameMatchMethodPointcutAdvisor中 -->  <bean id="aopMethodBeforeInterceptor" class="org.springframework.aop.support. NameMatchMethodPointcutAdvisor">        <!-- 拦截器的实现类-->        <property name="advice">               <bean class="com.clf.spring.MethodBeforeInterceptor">        </property>        <!-- 欲拦截的方法名-->        <property name="mappedName" value="withAop">        </property>  </bean>     <!-- 类似的方式配置返回后前拦截器MethodAfterInteceptor -->  <bean id="aopMethodAfterInterceptor" class="org.springframework.aop.support. NameMatchMethodPointcutAdvisor">        <property name="advice">               <bean class="com.clf.spring.MethodAfterInteceptor">        </property>        <property name="mappedName" value="withAop">        </property>  </bean>     <!-- 类似的方式配置异常前拦截器MethodAfterInteceptor-->  <bean id="aopThrowsInterceptor" class="org.springframework.aop.support. NameMatchMethodPointcutAdvisor">        <property name="advice">               <bean class="com.clf.spring.ThrowsInterceptor">        </property>        <property name="mappedName" value="withoutAop">   </property>  </bean>     <!-- Service实现类,安装到ProxyFactoryBean-->  <bean id="aopService" class="org.springframework.aop.ProxyFactoryBean">        <!-- 安装拦截器-->        <property name="interceptorNames">               <list>                      <value>aopMethodBeforeInterceptor</value>                      <value>aopMethodAfterInterceptor</value>                      <value>aopThrowsInterceptor</value>               </list>        </property>        <!—被拦截的对象-->        <property name="target">               <bean class="com.clf.spring.AopServiceImpl">                      <property name="name" value="HelloSpring"></property>               </bean>        </property>  </bean>

AOP相关概念

切面Aspect

在本例中,方法withAop()、withoutAop()中都有一些代码,这些代码可以看做是AOP中的切面,可以将切面理解为模块

通知Advisor

本例的三个拦截器都是实现自某个接口,从类名上看就知道三个拦截器都是AOP中的通知。一旦Spring符合条件,就会派发出通知,即一些需要执行的代码,能实现某种功能

切入点Pointcut

在配置拦截器时,XML中只配置了withAop()方法使用拦截器,而withoutAop()方法没有配置拦截器,这种配置是借助于org.springframework.aop.support. NameMatchMethodPointcutAdvisor完成的。这就是一个切入点,配置时可以使用通配符。该类明上也带有Advisor是因为它也是用通知实现的

 

简单地说,切入点负责往什么地方插入代码,而通知负责插入什么代码

Spring提供灵活的切入点配置,例如使用正则表达式

<bean id="advisorTest" class="org.springframework.aop.support.RegexMethodPointcutAdvisor">        <property name="interceptor">               <ref local="someInterceptor">        </property>        <property name="pattern">               <list>                      <value>.*get*</value>                      <value>.*set*</value>               </list>        </property>  </bean>