spring的AOP组件

spring的AOP组件是基于这样一种思想:让程序员把分散在代码中的重复功能提取出来,单独编写成一个类(spring叫通知advice),通过动态代理的手段再加入到需要它的地方。
 
1>.spring要求advice要按照它的要求进行编写。它给提供了四个接口可供使用,以便在目标方法执行的不同时期不同情况下,能够触发执行advice里的方法:
    MethodBeforeAdvice:在目标方法调用之前触发执行它的方法before(...);
   AfterReturningAdvice:在目标方法返回值之前触发执行它的方法afterReturning(...);
   MethodInterceptor:      可以在它的方法invoke(...)执行过程中调用目标方法;
   ThrowsAdvice:             在目标方法发生异常时触发执行它实现类里面的方法afterThrowing(...)。
 
2>.spring通过类org.springframework.aop.framework.ProxyFactoryBean来实现把advice和目标类结合起来完成动态代理功能,向用户提供所需要的代理类。
 
目标类实现的接口:
public interface StudentDao {
  public void test1();

  public void test2() throws Exception;
}
 
目标类:
public class StudentDaoImpl implements StudentDao {
  public void test1() {
    try {
      Thread.sleep(2000);//用来使测试时间更加明显
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println("@@@@执行目标方法:test1()@@@@");
  }
    
  public void test2() throws Exception {
    System.out.println("####执行目标方法:test2()####");
    throw new SQLException("test2 has SQLException");
  }
}
 
Advice:
public class SecurityAdvice implements MethodBeforeAdvice {
  /*    
    * method: 目标方法
    * args: 目标方法的参数列表
    * target: 目标对象
    */

  @Override
  public void before(Method method, Object[] args, Object target)
      throws Throwable {
    System.out.println("====security check for: "+method.getName()+" ====");
  }
}
 
public class LoggingAdvice implements AfterReturningAdvice {
  /*    
    * returnValue: 目标方法的返回值
    * method: 目标方法
    * args: 目标方法的参数列表
    * target: 目标对象
    */

  @Override
  public void afterReturning(Object returnValue, Method method, Object[] args,
      Object target) throws Throwable {
    System.out.println("****"+method.getName()+" run at "+new Date()+" ****");
  }
}
 
public class PerformanceAdvice implements MethodInterceptor {
  /**
    * invocation: 是对目标方法的一个封装,不但包含了目标方法本身以及它的参数列表,还包括目标对象.
    */

  @Override
  public Object invoke(MethodInvocation invocation) throws Throwable {
    Long beginTime=System.currentTimeMillis();
    Object ret=invocation.proceed();//对外提供了此方法,用来执行目标方法.
    Long endTime=System.currentTimeMillis();
    System.out.println("####"+invocation.getMethod().getName()+" used "+(endTime-beginTime)+" ms####");
    return ret;
  }
}
 
public class MyThrowsAdvice implements ThrowsAdvice {
  /**
    * ThrowsAdvice接口本身并不包含任何方法,但spring要求它里面要触发的方法必须叫afterThrowing,并且允许程序员无限重载之。其实这也是不得已的做法,因为spring不可能事先定义好目标方法要发生的所有异常情况,交给程序员自行处理也许是个最好的选择。
    *需要特别指出的是:当异常发生重叠时,它采用的是最精确匹配执行。
    * @param e: 目标方法抛出的异常对象
    */

  public void afterThrowing(Exception e) {// 目标方法发生Exception时执行本方法
    System.out.println("@@@@catch Exception " + e.getMessage() + "@@@@");
  }

  public void afterThrowing(RuntimeException e) {// 目标方法发生RuntimeException时执行本方法
    System.out.println("@@@@catch RuntimeException " + e.getMessage()+ "@@@@");
  }

  public void afterThrowing(SQLException e) {// 目标方法发生SQLException时执行本方法
    System.out.println("@@@@catch SQLException " + e.getMessage() + "@@@@");
  }

  public void afterThrowing(IOException e) {// 目标方法发生IOException时执行本方法
    System.out.println("@@@@catch IOException " + e.getMessage() + "@@@@");
  }
}
 
配置文件:
<beans>
  <bean id="target" class="com.yangfei.spring.advice.StudentDaoImpl">
  </bean>
  <bean id="before" class="com.yangfei.spring.advice.SecurityAdvice"></bean>
  <bean id="after" class="com.yangfei.spring.advice.LoggingAdvice"></bean>
  <bean id="interceptor" class="com.yangfei.spring.advice.PerformanceAdvice"></bean>
  <bean id="throws" class="com.yangfei.spring.advice.MyThrowsAdvice"></bean>
  <bean id="dao" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target"><!-- 目标类 -->
      <ref bean="target"/>
    </property>
    <property name="interceptorNames"><!-- Adivice -->
      <list>
        <value>before</value>
        <value>after</value>
        <value>interceptor</value>
        <value>throws</value>
      </list>
    </property>
    <property name="interfaces"><!-- 目标类实现的接口 -->
      <list>
        <value>com.yangfei.spring.advice.StudentDao</value>
      </list>
    </property>
  </bean>
</beans>
 
测试类:
  public static void main(String[] args) throws Exception{
    ApplicationContext ctx=new ClassPathXmlApplicationContext("test.xml");
    StudentDao dao=(StudentDao)ctx.getBean("dao");
    dao.test1();
    System.out.println();
    dao.test2();
  }
 
运行结果:
====security check for: test1 ====
@@@@执行目标方法:test1()@@@@
####test1 used 2000 ms####
****test1 run at Sat Dec 19 10:04:28 CST 2009 ****
 
====security check for: test2 ====
####执行目标方法:test2()####
@@@@catch SQLException test2 has SQLException@@@@
Exception in thread "main" java.sql.SQLException: test2 has SQLException
 at com.cernet.spring.advice.StudentDaoImpl.test2(StudentDaoImpl.java:30)
.......
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值