Spring AOP 之AfterReturningAdvice & MethodBeforeAdv

Spring框架中成功吸引人的一点就是容器事务的管理,提供了一个轻量级的容器事务处理,针对的对象是普通的java类,使用Spring事务管理的话 ,你可以按照自己的业务把一些相关的方法纳入其事务管理里面,这就避免了程序员在处理事务的过程中繁琐的工作.同时这些也是ejb2.X规范里 面吸引人的一点,这在spring里面都很好的提供.虽然在跨容器的事务管理,spring里面并没有提供,但是对于一般的web程序来说,也不需要仅仅 为了那些功能而不得不使用ejb.不过,最近jboss的嵌入式的ejb容器也可以做的更小了,也是开源中的选择之一.无论技术是怎样发展的,当前,我 们先来研究其中AOP实现的方法.
  
  事实上,Spring中的事务处理是通过AOP思想来实现的,Spring AOP与Aspect J和JBoss具有很 大的不同,首先,使用Spring AOP框架的用户要记住的一点是,Spring AOP针对的是方法层次上的实现,而其他两者对字段也提供了支持.说到 Spring AOP的内幕,其实也不难,对于有接口的类,使用的是Java内部类提供的Proxy;而对于那些不实现接口的类,使用的是cglib库,动态创建一 个子类来实现.
  
  在Spring AOP中提供了4种处理切入类型:around,before,after,introduction.顾名思义,
  
   1)around是针对具体的某个切入点的方法(比如,现在有个OrderBook方法,around的切入类型是就这个方法的内部调用,是通过java的元数据,在 运行时通过Method.invoke来调用,具有返回值,当发生意外的时候会终止.记住的一点是,返回值.);
  
   2)before是在方法调用前 调用(在OrderBook方法前调用,但是没有返回值,同时在通常意外情况下,会继续运行下一步方法.记住的一点是没有返回值);
  
   3)after和before刚好相反,没有什么特别的地方.
  
   4)introduction是一个更加特殊的,但功能更加强大的切入类型.比如(你现 在有Book对象,Computer对象,还有几十个这种业务对象,现在你希望在每个这样的对象中都加入一个记录最后修改的时间.但是你又不希望对每 个类都进行修改,因为太麻烦了,同时更重要的一点,破坏了对象的完整性,说不定你以后又不需要这个时间数据了呢...这时怎么办呢?Spring AOP就为你专门实现这种思想提供了一个切入处理,那就是introduction.introduction可以为你动态加入某些方法,这样可以在运行时,强制转换 这些对象,进行插入时间数据的动作,更深的内幕就是C++虚函数中的vtable思想).不过这种动态是以性能作为代价的,使用之前要慎重考虑,这里 我们谈的是技术,所以就认为他是必需的.

程序包图结构如下图:


 

下面先将代码贴出再说:

Hello.java

 

/** */ /**
 * BeforeAdviceSample
 
*/
package  com.fhway.spring.aop;

/** */ /**
 * 
@author fuhw
 * 2006-10-5   下午12:17:40
 
*/
public   interface  Hello  ... {
    
public void sayHello(String name);
}

HelloImpl.java

 

/** */ /**
 * BeforeAdviceSample
 
*/
package  com.fhway.spring.aop;

/** */ /**
 * 
@author fuhw 2006-10-5 下午01:07:03
 
*/
public   class  HelloImpl  implements  Hello  ... {
    
public void sayHello(String name) ...{
        System.out.println(
"Hello, the world.Your name is " + name);
    }

}

TestAfterAdvice.java

 

/** */ /**
 * BeforeAdviceSample
 
*/
package  com.fhway.spring.aop;

import  java.lang.reflect.Method;

import  org.springframework.aop.AfterReturningAdvice;

/** */ /**
 * 
@author fuhw
 * 2006-10-5   下午01:31:06
 
*/
public   class  TestAfterAdvice  implements  AfterReturningAdvice ... {

    
public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable ...{
        
// TODO Auto-generated method stub
        System.out.println("Thank you,Come again! ");
    }

}

TestBeforeAdvice.java

 

/** */ /**
 * BeforeAdviceSample
 
*/
package  com.fhway.spring.aop;

import  java.lang.reflect.Method;

import  org.springframework.aop.MethodBeforeAdvice;
/** */ /**
 * 
@author fuhw
 * 2006-10-5   下午01:14:06
 
*/
public   class  TestBeforeAdvice  implements  MethodBeforeAdvice ... {
    
public void before(Method method,Object[] args,Object target) throws Throwable...{
        System.out.println(
"Hi,this is "+this.getClass().getName());
   }


}

Main.java

 

/** */ /**
 * BeforeAdviceSample
 
*/
package  com.fhway.spring.aop;

import  org.springframework.context.ApplicationContext;
import  org.springframework.context.support.FileSystemXmlApplicationContext;

/** */ /**
 * 
@author fuhw 2006-10-5 下午01:16:37
 
*/
public   class  Main  ... {
    
public static void main(String[] args) throws Exception ...{
        ApplicationContext ctx 
= new FileSystemXmlApplicationContext("applicationContext.xml");
        Hello h 
= (Hello) ctx.getBean("hello");
        h.sayHello(
"fhway");
    }


}

applicationContext.xml

 

<? xml version="1.0" encoding="UTF-8" ?>
<! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 

"http://www.springframework.org/dtd/spring-beans.dtd"
>

< beans >

    
< bean  id ="beanTarget"  class ="com.fhway.spring.aop.HelloImpl" ></ bean >

<!--  1.MethodBeforeAdvice  -->
    
< bean  id ="theBeforeAdvice"
        class
="com.fhway.spring.aop.TestBeforeAdvice" >
    
</ bean >
<!--  2.AfterReturningAdvice  -->
    
< bean  id ="theAfterAdvice"
        class
="com.fhway.spring.aop.TestAfterAdvice" >
    
</ bean >


    
< bean  id ="theAdvisor"
        class
="org.springframework.aop.support.NameMatchMethodPointcutAdvisor" >
        
< property  name ="advice" >
<!--  
            <ref local="theBeforeAdvice" />
-->              < ref  local ="theAfterAdvice"   />
        
</ property >
        
        
< property  name ="mappedName" >
            
< value > say* </ value >
        
</ property >                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
    
</ bean >

    
< bean  id ="hello"
        class
="org.springframework.aop.framework.ProxyFactoryBean" >
        
< property  name ="proxyInterfaces" >
            
< value > com.fhway.spring.aop.Hello </ value >
        
</ property >
        
< property  name ="target" >
            
< ref  local ="beanTarget"   />
        
</ property >
        
< property  name ="interceptorNames" >
            
< list >
                
< value > theAdvisor </ value >
            
</ list >
        
</ property >
    
</ bean >

</ beans >

         1.从代码可以看出Hello.java是target的实现接口;而HelloImpl.java是其实现;

         2.TestAfterAdvice.java为AfterReturningAdvice的AOP实现方式;TestBeforeAdvice.java为MethodBeforeAdvice的实现方式;Main.java为测试方法;OK?

         3.关于applicationContext.xml应该是我们要谈的重点;"org.springframework.aop.framework.ProxyFactoryBean"有几个属性"proxyInterfaces"(代理接口)"target"(代理目标),"interceptorNames"(目标的通知bean名称),其他属性我将在下一篇文章中介绍;

      4.<!-- 1.MethodBeforeAdvice -->&<!-- 2.AfterReturningAdvice -->是可选的切入类型,在测试的时候我们任选其一就可以了,在通知置入点的配置bean "theAdvisor"的23-25的代码就可以对这个类型进行切换的;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值