Spring AOP应用实例demo

AOPAspect-Oriented Programming,面向方面编程),可以说是OOPObject-OrientedPrograming,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。

 

OOP的问题,AOP的补充

 

当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

 

所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

 

Spring中对 AOP的支持

 

spring AOP代理由Spring IoC容器负责生成、管理,其依赖关系也由 IoC容器负责管理。因此,AOP代理可以直接使用容器中的其他 Bean实例作为目标,这种关系可由 IoC容器的依赖注入提供。Spring默认使用 Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了。当需要代理的类不是代理接口的时候, Spring自动会切换为使用 CGLIB代理,也可强制使用 CGLIB

 

程序员参与部分 

 

AOP编程其实是很简单的事情。纵观 AOP编程,其中需要程序员参与的只有三个部分:

 

   定义普通业务组件。

   定义切入点,一个切入点可能横切多个业务组件。

   定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作。

 

所以进行 AOP编程的关键就是定义切入点和定义增强处理。一旦定义了合适的切入点和增强处理,AOP框架将会自动生成AOP代理,即:代理对象的方法 =增强处理 +被代理对象的方法。

 

Spring中使用方式:

 

基于 Annotation的“零配置”方式。

 

1)启动注解,配置文件applicationContext.xml

 

[html] view plain copy
 
 print?
  1. <!-- 启动对@AspectJ注解的支持 -->       
  2. <aop:aspectj-autoproxy/>  
  3.   
  4. <bean id="user" class="com.tgb.spring.aop.IUserImpl"/>  
  5.   
  6. <bean id="check" class="com.tgb.spring.aop.CheckUser"/>  

 

2)编写切面类

 

[java] view plain copy
 
 print?
  1. package com.tgb.spring.aop;  
  2.   
  3. import org.aspectj.lang.ProceedingJoinPoint;  
  4. import org.aspectj.lang.annotation.After;  
  5. import org.aspectj.lang.annotation.Around;  
  6. import org.aspectj.lang.annotation.Aspect;  
  7. import org.aspectj.lang.annotation.Before;  
  8. import org.aspectj.lang.annotation.Pointcut;  
  9.   
  10. @Aspect   
  11. public class CheckUser {  
  12.   
  13.     @Pointcut("execution(* com.tgb.spring.aop.*.find*(..))")  
  14.     public void checkUser(){  
  15.         System.out.println("**************The System is Searching Information For You****************");  
  16.     }  
  17.       
  18.     @Pointcut("execution(* com.tgb.spring.aop.*.add*(..))")  
  19.     public void checkAdd(){  
  20.         System.out.println("**************<< Add User >> Checking.....***************");  
  21.     }  
  22.       
  23.     @Before("checkUser()")  
  24.     public void beforeCheck(){  
  25.         System.out.println(">>>>>>>> 准备搜查用户..........");  
  26.     }  
  27.       
  28.     @After("checkUser()")  
  29.     public void afterCheck(){  
  30.         System.out.println(">>>>>>>> 搜查用户完毕..........");  
  31.     }  
  32.   
  33.     @Before("checkAdd()")  
  34.     public void beforeAdd(){  
  35.         System.out.println(">>>>>>>> 增加用户--检查ing..........");  
  36.     }  
  37.       
  38.     @After("checkAdd()")  
  39.     public void afterAdd(){  
  40.         System.out.println(">>>>>>>> 增加用户--检查完毕!未发现异常!..........");  
  41.     }  
  42.       
  43.      //声明环绕通知    
  44.     @Around("checkUser()")    
  45.     public Object doAround(ProceedingJoinPoint pjp) throws Throwable {    
  46.         System.out.println("进入方法---环绕通知");    
  47.         Object o = pjp.proceed();    
  48.         System.out.println("退出方法---环绕通知");    
  49.         return o;    
  50.     }    
  51. }  

 

3)定义接口

 

[java] view plain copy
 
 print?
  1. package com.tgb.spring.aop;  
  2.   
  3. public interface IUser {  
  4.   
  5.     public String findUser(String username);  
  6.     public void addUser(String username);  
  7.     public void findAll();  
  8. }  

 

 

4)定义实现

[java] view plain copy
 
 print?
  1. package com.tgb.spring.aop;  
  2.   
  3. import java.util.HashMap;  
  4. import java.util.Map;  
  5.   
  6. public class IUserImpl implements IUser {  
  7.   
  8.     public static Map map = null;  
  9.     public static void init(){  
  10.         String[] list = {"Lucy", "Tom", "小明", "Smith", "Hello"};  
  11.         Map tmp = new HashMap();  
  12.         for(int i=0; i<list.length; i++){  
  13.             tmp.put(list[i], list[i]+"00");  
  14.         }  
  15.         map = tmp;  
  16.     }  
  17.     public void addUser(String username) {  
  18.         init();  
  19.         map.put(username, username+"11");  
  20.         System.out.println("--------------【addUser】: "+username+" --------------");  
  21.         System.out.println("【The new List:"+map+"】");  
  22.     }  
  23.   
  24.     public void findAll() {  
  25.         init();  
  26.         System.out.println("---------------【findAll】: "+map+" ------------------");  
  27.     }  
  28.   
  29.     public String findUser(String username) {  
  30.         init();  
  31.         String password = "没查到该用户";  
  32.         if(map.containsKey(username)){  
  33.             password = map.get(username).toString();  
  34.         }  
  35.         System.out.println("-----------------【findUser】-----------------");  
  36.         System.out.println("-----------------Username:"+username+"-----------------");  
  37.         System.out.println("-----------------【Result】:"+password+"------------------");  
  38.         return password;  
  39.           
  40.     }  
  41.   
  42. }  

 

5测试

[java] view plain copy
 
 print?
  1. public class Test {  
  2.       
  3.     public static void main(String as[]){  
  4.         BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");  
  5.         IUser user = (IUser) factory.getBean("user");  
  6.         user.findAll();  
  7.           
  8.         User u = new User();  
  9. //      u.setUsername("Tom");  
  10. //      user.findUser(u.getUsername());  
  11.           
  12.         /*u.setUsername("haha"); 
  13.         user.addUser(u.getUsername());*/  
  14.     }  
  15. }  

 

 

执行结果:

 

进入方法---环绕通知

>>>>>>>>准备搜查用户..........

---------------【findAll】: {Smith=Smith00, Tom=Tom00, 小明=小明00, Lucy=Lucy00,Hello=Hello00} ------------------

退出方法---环绕通知

>>>>>>>> 搜查用户完毕..........

 

注:@Before是在所拦截方法执行之前执行一段逻辑。@After是在所拦截方法执行之后执行一段逻辑。@Around是可以同时在所拦截方法的前后执行一段逻辑。

 

以上是针对注解的方式来实现,那么配置文件也一样,只需要在applicationContext.xml中添加如下代码:

[html] view plain copy
 
 print?
  1. <!--  <aop:config>  
  2.         <aop:pointcut id="find" expression="execution(* com.tgb.spring.aop.*.find*(..))" />  
  3.         <aop:pointcut id="add"   expression="execution(* com.tgb.spring.aop.*.add*(..))" />  
  4.           
  5.         <aop:aspect id="checkUser" ref="check">  
  6.             <aop:before method="beforeCheck" pointcut-ref="find"/>  
  7.             <aop:after method="afterCheck" pointcut-ref="find"/>  
  8.         </aop:aspect>  
  9.           
  10.         <aop:aspect id="checkAdd" ref="check">  
  11.             <aop:before method="beforeAdd" pointcut-ref="add"/>  
  12.             <aop:after method="afterAdd" pointcut-ref="add"/>  
  13.         </aop:aspect>  
  14.       
  15.     </aop:config>-->  

 

 

总结:

 

以上是简单介绍了一下如何使用Spring AOP,在使用的过程中也加深我们对AOP思想的理解,其实AOP就是要我们实现热插拔效果,下篇会继续介绍Spring AOP的实现原理。

 

附:在使用过程中注意JDK版本与易用的aspectJrt的版本问题

posted @ 2017-06-18 21:25  N神3  阅读(137)  评论(0编辑  收藏  举报