标签:
AOP(Aspect-Oriented Programming,面向方面编程),可以说是OOP(Object-OrientedPrograming,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。
当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
Spring中 AOP代理由Spring的 IoC容器负责生成、管理,其依赖关系也由 IoC容器负责管理。因此,AOP代理可以直接使用容器中的其他 Bean实例作为目标,这种关系可由 IoC容器的依赖注入提供。Spring默认使用 Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了。当需要代理的类不是代理接口的时候, Spring自动会切换为使用 CGLIB代理,也可强制使用 CGLIB。
AOP编程其实是很简单的事情。纵观 AOP编程,其中需要程序员参与的只有三个部分:
定义普通业务组件。
定义切入点,一个切入点可能横切多个业务组件。
定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作。
所以进行 AOP编程的关键就是定义切入点和定义增强处理。一旦定义了合适的切入点和增强处理,AOP框架将会自动生成AOP代理,即:代理对象的方法 =增强处理 +被代理对象的方法。
基于 Annotation的“零配置”方式。
(1)启动注解,配置文件applicationContext.xml
<!-- 启动对@AspectJ注解的支持 --> <aop:aspectj-autoproxy/> <bean id="user" class="com.tgb.spring.aop.IUserImpl"/> <bean id="check" class="com.tgb.spring.aop.CheckUser"/>
(2)编写切面类
package com.tgb.spring.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public class CheckUser { @Pointcut("execution(* com.tgb.spring.aop.*.find*(..))") public void checkUser(){ System.out.println("**************The System is Searching Information For You****************"); } @Pointcut("execution(* com.tgb.spring.aop.*.add*(..))") public void checkAdd(){ System.out.println("**************<< Add User >> Checking.....***************"); } @Before("checkUser()") public void beforeCheck(){ System.out.println(">>>>>>>> 准备搜查用户.........."); } @After("checkUser()") public void afterCheck(){ System.out.println(">>>>>>>> 搜查用户完毕.........."); } @Before("checkAdd()") public void beforeAdd(){ System.out.println(">>>>>>>> 增加用户--检查ing.........."); } @After("checkAdd()") public void afterAdd(){ System.out.println(">>>>>>>> 增加用户--检查完毕!未发现异常!.........."); } //声明环绕通知 @Around("checkUser()") public Object doAround(ProceedingJoinPoint pjp) throws Throwable { System.out.println("进入方法---环绕通知"); Object o = pjp.proceed(); System.out.println("退出方法---环绕通知"); return o; } }
(3)定义接口
package com.tgb.spring.aop; public interface IUser { public String findUser(String username); public void addUser(String username); public void findAll(); }
(4)定义实现
package com.tgb.spring.aop; import java.util.HashMap; import java.util.Map; public class IUserImpl implements IUser { public static Map map = null; public static void init(){ String[] list = {"Lucy", "Tom", "小明", "Smith", "Hello"}; Map tmp = new HashMap(); for(int i=0; i<list.length; i++){ tmp.put(list[i], list[i]+"00"); } map = tmp; } public void addUser(String username) { init(); map.put(username, username+"11"); System.out.println("--------------【addUser】: "+username+" --------------"); System.out.println("【The new List:"+map+"】"); } public void findAll() { init(); System.out.println("---------------【findAll】: "+map+" ------------------"); } public String findUser(String username) { init(); String password = "没查到该用户"; if(map.containsKey(username)){ password = map.get(username).toString(); } System.out.println("-----------------【findUser】-----------------"); System.out.println("-----------------Username:"+username+"-----------------"); System.out.println("-----------------【Result】:"+password+"------------------"); return password; } }
(5)测试
public class Test { public static void main(String as[]){ BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml"); IUser user = (IUser) factory.getBean("user"); user.findAll(); User u = new User(); // u.setUsername("Tom"); // user.findUser(u.getUsername()); /*u.setUsername("haha"); user.addUser(u.getUsername());*/ } }
执行结果:
进入方法---环绕通知
>>>>>>>>准备搜查用户..........
---------------【findAll】: {Smith=Smith00, Tom=Tom00, 小明=小明00, Lucy=Lucy00,Hello=Hello00} ------------------
退出方法---环绕通知
>>>>>>>> 搜查用户完毕..........
注:@Before是在所拦截方法执行之前执行一段逻辑。@After是在所拦截方法执行之后执行一段逻辑。@Around是可以同时在所拦截方法的前后执行一段逻辑。
以上是针对注解的方式来实现,那么配置文件也一样,只需要在applicationContext.xml中添加如下代码:
<!-- <aop:config> <aop:pointcut id="find" expression="execution(* com.tgb.spring.aop.*.find*(..))" /> <aop:pointcut id="add" expression="execution(* com.tgb.spring.aop.*.add*(..))" /> <aop:aspect id="checkUser" ref="check"> <aop:before method="beforeCheck" pointcut-ref="find"/> <aop:after method="afterCheck" pointcut-ref="find"/> </aop:aspect> <aop:aspect id="checkAdd" ref="check"> <aop:before method="beforeAdd" pointcut-ref="add"/> <aop:after method="afterAdd" pointcut-ref="add"/> </aop:aspect> </aop:config>-->
以上是简单介绍了一下如何使用Spring AOP,在使用的过程中也加深我们对AOP思想的理解,其实AOP就是要我们实现热插拔效果,下篇会继续介绍Spring AOP的实现原理。
附:在使用过程中注意JDK版本与易用的aspectJrt的版本问题
标签:
原文地址:http://blog.csdn.net/hejingyuan6/article/details/44279239