疯狂

STANDING ON THE SHOULDERS OF GIANTS
posts - 481, comments - 486, trackbacks - 0, articles - 1
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

通过Annotation来实现AOP(转)

Posted on 2008-10-20 12:45 疯狂 阅读(2067) 评论(0)  编辑  收藏 所属分类: java
文章来源:http://jummy.javaeye.com/blog/255126,thank u,jummy。
 

首先写个题记吧 --- 如果你是 Spring 高手。那么我所写的文章对你可能一文不值 ( 至少最近几篇 ) ,就等于说让你看小学课本 ( 本人水平也一般 ) ;如果你觉得你是个新手,希望这篇文章没有浪费你的时间,让你有所收获!

前两篇文章一直不断的在给 Spring AOP 做铺垫。如果你刚接触 AOP 不久还是希望你从 JDK 动态代理那篇文章一一看起,那也是我学习 AOP 的一个缩影。我觉得今天该写写所谓 Spring 中的 AOP 了,其实这并不是个什么新鲜事物只是 Spring 将它纳入自己的框架取名曰: AOP( 面向切面编程 )

Spring AOP 有两种实现技术:一种不太用的是通过 Annotation( 注解 ) 实现。另一种方法就是通过配置文件来实现也就是我们的 configuration ,通过配置达到目的。 ( 这也是现在提倡的用法 ) 。但是为了理解原理,我还是从 Annotation 说起吧。懂了原理其他就好办了。

Annotation 方式实现 AOP ,首先得添加架包支持这两个包就是: aspectjrt.jar aspectjweave.jar 。当然你还得添加一些其他的 Spring 支持。我们通过代码来来讲解吧

因为是面向切面编程了,那知道横切关注点了(假如我要实现安全验证),那我们得将其抽取出来,模块成一个类(也就是 AOP 的关键工作寻找切面 ,或者说自己创建切面 。这个是可以按需所求的,就是说你可以设计自己需要功能的切面)。那我就创建一个安全类吧:但为了体现面向接口编程的思想,我们想抽取成接口然后在通过接口的实现类来实现这一功能:

创建接口:(这个是普通类的接口,也就是后面要使用切面的目标类的类接口)        

 
  1. package com.jummy.aop;   
  2.   
  3. public interface UserManager {   
  4.  public void  addUser(String string,String name);   
  5.  public void delUser(int id);   
  6.  public void modifyUser(int id,String name,int age);   
  7. }  
 

           

接着是接口的实现类: ( 截图比较模糊 ,我附有源码的 )

 
  1. package com.jummy.aop;   
  2. public class UserManagerImpl implements UserManager {   
  3.   
  4.     public void addUser(String id, String name) {   
  5.        
  6.         System.out.println("---UsreManagerImpl中的addUser方法的实现-----");   
  7.     }   
  8.   
  9.     public void delUser(int id) {   
  10.         System.out.println("-----delUser方法的实现-----");   
  11.     }   
  12.   
  13.     public void modifyUser(int id, String name, int age) {   
  14.         System.out.println("----modifyUser方法的实现-----");   
  15.     }   
  16.   
  17. }  
 

 

创建切面的接口:(所有的切面都可以从此接口继承,这里这样写主要是体现面向接口编程的思想。这里提供实现安全验证的接口)

       

 
  1. package com.jummy.aop;   
  2.   
  3. public interface MySecurityManager {   
  4.     public void security();   
  5.     //也可以添加多个方法   
  6.     //public void security2();   
  7. }  
 

 

创建切面 ( ) :这是重点,除了实现接口中的方法以外,还需要在 Aspect 中定义 Pointcut 以及 Advice 。当然这一切是通过文章开头说的 Aspectj 实现的,主要功能有两个架包提供我们可直接引用( aspectjrt.jar aspectjweave.jar )!

 
  1. import org.aspectj.lang.annotation.Aspect;   
  2. import org.aspectj.lang.annotation.Before;   
  3. import org.aspectj.lang.annotation.Pointcut;   
  4. /*  
  5.  * 我们已经把横切关注点抽取出来了  
  6.  * 那就需要定义我们的Aspect了(类)  
  7.  */  
  8. @Aspect  
  9. //使用@Aspect之前记得要引入aspectjrt.jar和aspectjweaver.jar   
  10. public class MySecurityManagerImpl implements MySecurityManager {   
  11.   
  12.     /*  
  13.      * 定义切入点,切入  
  14.      *   
  15.      * 该方法只是一个标识(而且只作为标识并不是常态下的方法,并不供人调用所以没有返回值最好设置为private), 切入点的内容是一个表达式。  
  16.      * 根据这个表达式就可以用来判断切入哪些对象的哪些方法  
  17.      */  
  18.     @Pointcut("execution(* add*(..))")   
  19.     /*  
  20.      * 下面对表达式简单说一下: execution(* add*(..))第一个*说匹配是方法的任意返回值类型       
  21.      * 待会可以试验一下。add*就是表示以add开头的方法名都可以匹配想到正则表达式了吗? (..)这两个就是表示方法里所传递的参数类型也是任意匹配。  
  22.      * 具体的请参考spring的开发手册, 这一点Spring讲的比较清楚。  
  23.      *   
  24.      */  
  25.     private void addAllMethod() {   
  26.     }   
  27.   
  28.     /*  
  29.      * 定义Advice,标识在哪些切入点(切入点有ADD这是我们上面通过pointcut定义的。当然你也可以定义别的)  
  30.      * 的何处(何处就是指是切入点的前面呢?后面?还是其他情况)织入通知 当然除了before还有其他类型的通知。这里就不在累赘了  
  31.      *   
  32.      */  
  33.     @Before("addAllMethod()")   
  34.     public void security() {   
  35.         System.out.println("-----调用security方法-------");   
  36.     }   
  37.     /*这里也可以添加一些其他的前置方法  
  38.      * @Before("addAllMethod()")  
  39.     public void security2() {  
  40.         System.out.println("-----调用security方法2-------");  
  41.     }  
  42. */  
  43. }  
 

所有原理我都注释在源码中。其中在 Aspect 中需要做的就是定义 Pointcut 以及 Advice 。在定义 Pointcut 的过程中我们需要注意几点:首先在 Aspectj 的支持下, @Pointcut(“execution(* add*(..))”) 来实现。表达式我不多讲了自己看 Spring 的手册去吧。解释代码中 private void addAllMethod(){} 这是一个没有返回值的空方法体,它程序的实际运行过程中并不执行 ( 同时我们也不希望它被其他人调用所以设置为 private 以权限控制 ) 。它只是一个标识,这个标识会被下面代码中的 Advice( 也就是 @before(“addAllMethod()”) 调用。它的作用类似于变量名,起一个被调用的载体的作用 ( 所以称为标识 ) ;当然切入点的内容 ( 也就是引号里的一些表达式 ) 它们起到的作用就是来描述我们要切入哪些对象的哪些方法。

  OK pointcut 我们定义完成轮到 Advice 了。 Advice 是通过 @before(“addAllMethod()”) 来定义的,当然你可以是 after/throws 等等其他类型的通知。代码 public void security(){-------}

这就是通知的具体方法实现,也就是我前面说的要添加的安全验证。而且我申明了该验证在我执行所有的以 add 开头的方法之前执行。

   最后看看 spring 的配置文件里怎么写吧。

< aop:aspectj-autoproxy /> // 这里就是申明添加 aspectj 的支持,跟导入一个包类似的作用

<!— 下面是切面的注入 -->

  < bean id = "mySecurityManagerImpl" class = "com.jummy.aop.MySecurityManagerImpl" ></ bean >

  <!-- 这是目标对象的注入 -->

  < bean id = "userManagerImpl" class = "com.jummy.aop.UserManagerImpl" ></ bean >         

大家可能看到了,通过 Aspectj Annotation 支持实现 , 所有的 Advice Pointcut 啊都是直接在代码中实现的 当然里面具体逻辑是 Spring 帮你通过代理来实现的,毕竟你自己的实现类中(如 UserManagerImpl 类中并没有任何对安全性检查的调用)

  


只有注册用户登录后才能发表评论。


网站导航: