一、概念
AOP(Aspect-Oriented Programming,面向切面的编程),它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。它是一种新的方法论,它是对传统OOP编程的一种补充。
二、Aop原理
1.面向对象编程模型
OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。面向对象编程是关注将需求功能划分为不同的并且相对独立,封装良好的类,并让它们有着属于自己的行为,依靠继承和多态等来定义彼此的关系。面向对象编程着重于类的封装、对象的创建(生命周期)以及对象与对象之间的关系。
2.面向切面编程模型
Aop将应用系统分成两部分:核心业务逻辑和横向的通用逻辑,也就是所谓的方面。例如在面向对象编程中,除核心业务逻辑外还有涉及持久化管理、事物管理、安全管理、日志管理、调试管理等等。这样使用Aop就可以将处理方面的代码注入主程序,通常主程序的主要目的并不在于处理这些方面。
如果将面向对象看成编程模型的横向发展,那么面向切面编程模型是纵向发展,是面向对象的一个补充。
如图:
3.代理与容器
刚开始学习Aop感觉Aop很神奇,建立切面类(Aspect)、定义好切入点(Pointcut)、定义通知(Advice),发现这样就可以将切面类中的方法(Aop称为通知)随意的加到之前定义好的切入点上,即将特定的处理方面的代码注入到主程序中执行而不需要修改任何主程序代码。
如:
切面类:
package com.zhouxiang.log; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; /** * @author zx * */ @Aspect @Component public class Log { @Before("execution(public Boolean com.zhouxiang.service.LoginService.*(..))") public void loginLog() { System.out.println("start to login system!"); } @After("execution(public Boolean com.zhouxiang.service.LoginService.*(..))") public void loginLogSuccess() { System.out.println("end to login system!"); } }
目标对象:
package com.zhouxiang.service; import sun.security.jca.GetInstance.Instance; import com.zhouxiang.Dao.UserDao; public class LoginService { private UserDao userdao; public UserDao getUserdao() { return userdao; } public void setUserdao(UserDao userdao) { this.userdao = userdao; } public Boolean UserInfoValidate(String username, String password) { System.out.println(userdao.toString()); if (userdao.Query(username)!=null) return true; else return false; } }
当定义好切面、通知后只需要再确定切入点后,连接点就可以将指定的方法在指定的类中调用。此处加到了service逻辑中,还可以加到Action中、Dao中,只需要改一下定义的连接点(Joinpint)、切入点(Pointcut)而不需要修改代码。这样的功能Aop是如何实现的呢?我们假设应用中存在方法拦截器这样的功能是不是就相对容易多了呢?我们只需要配置好方法拦截器,当程序执行到指定的方法时,方法拦截器就会对其进行拦截然后转而执行切面逻辑然后再继续执行主程序。所以弄清Aop只需要弄清方法拦截器即可。相信熟悉Struts2的同学对方法拦截器一定不陌生,在Aop中使用的方法拦截器跟struts2中的方法拦截器实现原理一样都是借助代理来实现对特定方法的拦截。
Aop原理就弄明白了,当我们声明切面类后,根据定义好的连接点或切入点就可以得到我们要将切面业务逻辑织入到何处即目标对象,这样我们可以对目标对象创建一个代理对象,代理对象调用目标对象之前调用切面逻辑然后再调用目标对象中的业务逻辑即是整个Aop的流程。
整个流程不可缺少的就是容器,容器帮我们创建代理对象,将应该注入的目标对象偷偷换成代理对象注入到指定的组件中,保证完成整个过程的调用。
三、Aop与面向对象
OOP是关注将需求功能划分为不同的并且相对独立,封装良好的类,并让它们有着属于自己的行为,依靠继承和多态等来定义彼此的关系;AOP是希望能够将通用需求功能从不相关的类当中分离出来,能够使得很多类共享一个行为,一旦发生变化,不必修改很多类,而只需要修改这个行为即可。
AOP是使用切面(aspect)将横切关注点模块化,OOP是使用类将状态和行为模块化。在OOP的世界中,程序都是通过类和接口组织的,使用它们实现程序的核心业务逻辑是十分合适。但是对于实现横切关注点(跨越应用程序多个模块的功能需求)则十分吃力,比如日志记录,验证。面向切面编程,把散落在程序中的公共部分提取出来,做成切面类,这样的好处在于,代码的可重用,一旦涉及到该功能的需求发生变化,只要修改该代码就行,否则,你要到处修改。
四、总结
面向方面编程和面向对象编程不但不是互相竞争的技术而且彼此还是很好的互补。面向对象编程主要用于为同一对象层次的公用行为建模。它的弱点是将公共行为应用于多个无关对象模型之间。而这恰恰是面向方面编程适合的地方。有了 AOP,我们可以定义交叉的关系,并将这些关系应用于跨模块的、彼此不同的对象模型。AOP 同时还可以让我们层次化功能性而不是嵌入功能性,从而使得代码有更好的可读性和易于维护。