180 likes | 434 Views
AOP 编程. xx 年 xx 月 xx 日. AOP 概述. 什么是 AOP 什么时候需要用 AOP AOP 的相关术语. AOP 概述 > 什么是 AOP ?. Wiki 百科的答案: In software engineering, the programming paradigms of aspect-oriented programming (AOP), and aspect-oriented software development (AOSD)
E N D
AOP编程 xx年xx月xx日
AOP概述 • 什么是AOP • 什么时候需要用AOP • AOP的相关术语
AOP概述>什么是AOP? Wiki百科的答案: In software engineering, the programming paradigms of aspect-oriented programming (AOP), and aspect-oriented software development (AOSD) attempt to aid programmers in the separation of concerns, specifically cross-cutting concerns, as an advance in modularization. 面向方面编程/面向软件开发:一种在软件工程中,帮助程序员能够 将业务逻辑与交织在业务逻辑中的辅助功能相剥离的一种高级模块化 编程方式。
AOP概述>什么是AOP? AOP与传统OOP的不同之处就在于面向方面(Aspect),而什么是Aspect? 让我们用图片来直观的解释一下。 传统的OOP的方式采用的自上而下的解决方式,如下图中所示
AOP概述>什么是AOP? 现在为了要加入记录(Logging)与安全(Security)检查等服务, 对象的程序代码中若被硬生生的写入相关的Logging、Security程序片段, 则可使用以下图解表示出方面的概念 在这里,我们就可以将 日志处理和安全验证理解为 在这个业务中的两个方面。
AOP概述>什么时候需要用AOP 举个简单的银行转账例子: 从帐户A转移部分金额到帐户B上,大概的业务逻辑为: 1.用户进行转账操作,系统检查该用户是否有操作权限 2.系统操作记录日志,“某某要进行转账操作” 3.从帐户A中减去指定金额 4.从帐户B中添加指定金额 5.操作成功后,系统记录操作日志,“转账操作成功完成” 6.如果操作失败,事务回滚,并记录错误日志“转账操作失败”
AOP概述>什么时候需要用AOP 如果要实现上面的例子的话,我们可能会总结出以下若干个关注点: 1.转账操作 2.安全 3.日志 4.事务 分析一下,在这些关注点中,与业务直接相关(核心业务)的只有第一条, 其他的都是作为辅助功能出现的,这时就可以采用AOP的方式解决问题。
AOP概述>AOP的相关术语 联结点(JoinPoint):用来定义你在程序的哪里通过AOP加入新的逻辑, 对于Spring AOP,Jointpoint指的就是Method 通知(Advice):在特定联结点处执行的代码,这部分代码通常是要实现的 辅助功能,例如日志,安全检查等. 切入点(PointCut):定义某一个通知该如何执行的一组联结点。可以通过定义 复杂的切入点,来控制通知什么时候被执行。 方面(Aspect):一个关注点的模块化,这个关注点的实现可能横切多个对象。 事务管理是J2EE应用中一个很好的横切关注点的例子。在spring中方面用advisor 实现。 织入(weaving):织入是将方面真正加入程序代码的过程。静态AOP是在编译期 完成的,而动态的AOP是在运行期动态织入的。 目标(Target):如果一个对象的执行过程受到某个AOP的修改,则它就是一个目标 对象,也常称作被通知对象。
AOP的种类 前文提到过,AOP有静态与动态之分: 静态AOP:在静态AOP中,织入是编译过程的一个步骤, 换句话说编译之后的代码就是已经将通知织入到联结点上。 AspectJ采用的这种方式。 动态AOP:动态AOP是在运行期完成的织入操作,具体织 入方式也是根据不同的实现而不一样。Spring中的AOP属于 动态AOP,采用代理的实现方式。 这两者的主要区别: 具体采用那种方式,还要看实际的需求决定。
代理 上面说过,spring是通过代理实现AOP的,这里我们大概了解一下代理: 假设我们有一个Target类,我们想在这个target上加入一些其他的功能但又不想修改target类,这时我们引入另一个Proxy类, 如果target类是实现某个接口,我们就让这个proxy类也实现这个接口,并在原有功能基础上添加要实现的附加功能 如果target类不实现任何接口,我们就让这个proxy类继承自target类,做为target的一个子类,并添加要实现的附加功能。
代理 Spring中如何实现代理机制? --JDK动态代理和CGLIB代理 JDK代理是Spring中的基本代理方式,它只能代理接口,不能代理类。 虽然采用接口设计是很好的设计方式,但有时不能保证所有类都实现接口, 例如第三方类或者遗留代码等,这时就需要采用CGLIB的代理方式。 CGLIB的代理方式是在运行中随时为代理创建新的字节码,并尽可能的重用 已经生成的类的字节码,因此CGLIB代理执行被通知的方法的效率要略高于 JDK代理。CGLIB本身比较复杂,这里不做过多讨论,有兴趣可以访问: http://cglib.sourceforge.net/得到更详细信息。
AOP in Spring Spring中的五种不同的通知: 通知类型: 接口名称: 1.前置通知: MethodBeforeAdvice 2.后置通知: AfterReturningAdvice 3.包围通知: MethodInterceptor 4.抛出通知: ThrowAdvice
前置通知 使用前置通知必须将要实现的通知类实现MethodBeforeAdvice接口, 实现以下方法: Public void before(Method method, Object[] args, Object target ) Throws Throwable {} 其中各个参数的含义如下: Method:要执行的方法的名称 Args:要执行的方法的参数 Target:要执行的目标类,即target类。 可以在连接点执行前进行自定义的操作。在spring中能让你在方法 调用之前进行一些操作。 其中包括: 修改要执行的方法的参数; 阻止调用目标方法; 等。。。 参见login的例子
后置通知 后置通知在方法调用连接点返回后调用,与前置通知不一样的是,后置通知 不能修改原本程序的返回值,我们只能做一些新的操作。尽管如此,我们也可 以在后置通知中抛出异常,这样让调用方就会看到一个异常,而不是返回值。 使用后置通知的话,必须将要实现的通知类实现AfterReturningAdvice这个接口 ,实现以下方法: Public void afterReturning(Object returnValue,Method method,Object[] args, Object target) {} 与methodBeforeAdvice不同的是,在方法中加入了返回值returnValue这个参数。 请参见FruitFactory示例代码
包围通知 包围一个连接点的通知,如方法调用。这是最 强大的通知。Aroud通知在方法 调用前后完成自定义的行为。它们负责选择继续执行连接点或通过返回它们自己 的返回值或抛出异常来短路执行。 如果想创建一个包围通知,通知类实现MethodInterceptor接口,实现以下方法: public Object invoke(MethodInvocation invocation) throws Throwable { do something before invocation; invocation.proceed(); do something after invocation; } invoke()方法的MethodInvocation参数暴露了被调用的方法; 目标连接点; AOP代理以及传递给方法的参数。 请参见profile以及FruitFactory示例代码
抛出通知 抛出通知是在目标类在运行的时候抛出异常的时候,将被调用的方法,通知类 需要实现org.springframework.aop.ThrowsAdvice接口。 与其他的通知接口不同,ThrowAdvice接口作为一个标记接口,因此没有任何方法。 实现此接口的类需要实现如下格式的方法: afterThrowing([Method], [args], [target], Throwable subclass) 其中前三个参数为可选参数,只有最后一个参数为必须参数。 Method:被调用的方法 Args:传递给该方法的参数 Target:要执行的目标类,即target类 Throwable:抛出的exception 参见transferm代码
切入点Pointcut 前面已经讲到,切入点是用来定义某一个通知该如何执行的一组联结点。 当我们希望某个通知只有在某些特定条件下执行,这时就需要用到切入点。 Spring的切入点模型能够独立于通知类型被重用,换句话说一个切入点 有可能接受不同的通知 参见transferm代码