Expert one on one J2EE development without EJB 摘要(6)

 

基于AOP概念的声明性中间件

 

AOP还可以用于提供定制的声明性服务,从而更好的描述程序结构。

 

重点关注AOP的一个子集:方法拦截(method interception),这并不是AOP的全部。

 

拦截器也是一种久经实践检验的编程范式。

 

AOP面向方面编程。是与oop不同的角度看待应用程序。根据aop,系统被分解为方面(aspect)或关注点(concern),而不是对象。

 

衡量OOP是否成功的标准就在它在多大程度上避免了代码重复。

代码重复是最糟糕的代码臭味。只要出现重复的代码,必定有地方不对劲,要么设计有问题,要么实现有问题。

 

AOP将用于解决每个横切问题的代码收入一个独立的模块之中。

 

AOP这里,我们可以单独编写用于解决安全性问题的代码,并将其包装为一个方面(aspect)。然后AOP实现产品如何在运行时将方面织入(weave)到程序流程之中。

具体的织入策略有:代码生成和预编译;AOP语言;动态字节码生成;j2se动态代理。

 

 

import org.aopalliance.intercept.MethodInterceptor;

import org.aopalliance.intercept.MethodInvocation;

 

public class SecurityInteceptor implements MethodInterceptor {

 

public Object invoke(MethodInvocation arg0) throws Throwable {

doSecuriryWork();

return arg0.proceed();

 

}

 

protected void doSecuriryWork() throws Exception {

// do some security work

}

}

 

 

 

 

aop框架会提供某种机制,用于定义一组可以被拦截的方法(即切入点,pointcut

 

 

定义:

关注点concern:特定的问题、概念,或是应用程序的兴趣区间。

 

横切关注点crosscutting concern:一个关注点的实现代码散落在很多个类或者方法之中。

 

方面aspect:一个方面是对一个横切关注点的模块化,它将原本散落在各处的、用于实现这个关注点的代码规整到一处。

 

连接点(joint point):程序执行过程中的一点。如:

方法调用:对方法包括构造函数的调用,不过并非所有的AOP框架支持在对象构造时的增强(advice)。

字段访问:读或者写变量

异常抛出:特定的异常被抛出。

 

增强advice:在特定连接点执行的动作。很多AOP框架都以拦截器的形式来表示增强-- 所谓拦截器是这样的对象:当连接点被调用时,它会收到一个回调消息。增强的例子包括:

在允许执行特定连接点值钱,检查安全凭证,就像前面所示的例子那样

在执行某个方法连接点之前开启事务,在连接点执行完毕后提交或者回滚事务。

 

 

切入点pointcut:一组连接点的总称,用于指定某个增强应该在何时被调用。切入点常用正则表达式活着通配符语法来描述。有些AOP实现技术还支持切入点的组合。

 

引介(introduction):为一个现有的java类或接口添加方法或字段。这种技术可以用于实现java中的多继承。

 

织入weaving:将方面整合到完整的执行流程中。

 

目前Spring只支持基于拦截器的增强。

 

切入点分为静态标准切入点和动态切入点两类。静态标准切入点根据部署阶段的信息选择增强,譬如拦截特定类的所有getter方法。动态标准切入点则根据运行时的信息选择增强,譬如如果某方法的返回值为null,则将其纳入某切入点。

 

拦截器(interceptor):很多AOP框架用它来实现字段和方法的拦截。在连接点处挂接一条拦截器链。链条上的每个拦截器通常会调用下一个拦截器。

 

AOP代理:即被增强对象的引用。对于基于拦截的AOP框架来说,AOP代理的概念是根本。AOP代理可能是J2SE动态代理,也可能是借助字节码操作工具生成的。

 

目标对象:位于拦截器链末端的对象实例

 

 

一些OO设计模式解决了AOP的部分问题:

 

装饰者模式:允许在方法的前后增加行为。装饰器类和目标对象实现相同的接口,并且负责调用目标对象。然后加入人意的代码。

 

观察者模式

 

责任链模式:允许一个请求在一个对象链中进行,知道一个对象处理这个请求为止。

 

 

AOP实现策略,由弱至强:

J2SE动态代理

动态字节码生成

java代码生成

使用定制的类加载器

语言扩展

 

 

动态代理:动态代理非常强大,可以为一个或者多个接口创建实现类,而不需要实现类。动态代理最局限性在于,只能针对接口代理。

针对接口代理,spring默认使用动态代理。

 

动态字节码:CGLIBSpring中针对类的代理就是cglib。它可以针对指定的类动态的生成一个子类,并覆盖其中的方法,从而实现方法的拦截。cglib局限性在于,它是使用继承来实现代理的,因此无法对final方法的代理。

 

 

 

 

Spring AOP

方面一般是定义在xml中的。就像配置普通的javabean一样。方面的配置也可以使用spring ioc的功能,也可以选择以元数据驱动的方式。

一个增强指定了连接点处的行为。所有的增强都必须实现org.aopalliance.aop.Advice接口。

 

增强器(advisor包括两个方面:增强,以及用于说明在何处增强的切入点。增强器完整的模块化了一个方面。这样切入点和增强也可以各自独立服用。

 

引介是通过org.springframework.aop.IntroductionAdvisor实现的。和别的增强器不同,引介增强不包含切入点。引介是在类曾名上增强的,对方法级的没有作用。

 

spring不支持字段拦截。

只有通过Spring ioc容器获取的对象才能进行增强;不能在类装载器的层面进行增强。

和别的AOP技术一样,拦截器代码中没有强类型检查。不过,对于引介和抛出增强,Spring提供了强类型检查。

 

 

前增强可以在方法调用前增加自己的行为,不改变方法的返回值。

 

如果我们只对特定的某些异常感兴趣,那么使用抛出增强。如果连接点抛出了指定的异常,抛出增强就会被调用。

 

一个抛出增强可以包含多个增强方法,分别对应不同的异常类型。

 

各种增强都可以用切入点来指定应用目标。如果不使用切入点,则会针对目标上的所有方法进行增强。

 

 

public interface Pointcut {

 

/**

 * Return the ClassFilter for this pointcut.

 */

ClassFilter getClassFilter();

 

/**

 * Return the MethodMatcher for this pointcut.

 */

MethodMatcher getMethodMatcher();

 

// could add getFieldMatcher() without breaking most existing code

 

 

/**

 * Canonical Pointcut instance that always matches.

 */

Pointcut TRUE = TruePointcut.INSTANCE;

 

}

 

 

不要在应用程序上使用太多的方面。

 

 

SpringAOP的实践

 

Spring中,创建代理使用org.springframework.aop.framework.ProxyFactoryBean。这个类使得开发者完全控制切入点和要用的增强,以及增强的顺序。

 

要借助SpringProxyFactoryBean对一个目标进行增强,需要做以下几点:

将必要的切入点、拦截器和其他形式的增强在应用上下文中予以说明,通常多个AOP代理可以复用这些声明。

在应用上下文中声明将要被增强的目标对象

创建一个ProxyFactoryBean的实例,顶替目标对象被使用。该实例中必须包括所有的拦截器和增强器,以及目标对象。

 

 

 

可以对一个类的多个方法进行代理,可以代理一个类的所有接口,也可以从中挑选某些接口来代理。

 

ProxyFactoryBean类的interceptorNames属性可以接收一列字符串的参数,通过bean名称来指定要使用的拦截器,而不是直接引用拦截器bean组件。

 

其他对象应该引用businessObject,而不是引用businessObjectTarget,因为后者没有事务管理的增强。

 

 

如果我们希望只对特别指定的几个方法进行增强,就需要用到切入点(pointcut),而不是直接使用拦截器和其他增强。在Spring AOP框架中,如果直接使用拦截器之类的增强,等于使用了一个匹配目标对象所有方法调用的切入点。

 

 

Spring提供了通用的切入点:

根据正则表达式指定类名和方法名的切入点

控制流程切入点,通过调用栈驱动

用户实现应用程序专用切入点的便利超类。

 

 

如果只针对生命性的事务管理感兴趣,那么TransactionProxyFactoryBean会是个很好的选择。

 

 

 

 

自动代理

 

Spring还提供过来更为简单的通用做法,只需要在一个地方指定增强,即可将其应用于很多个业务对象。

Spring提供了几个自动代理创建器实现。这种功能通过组建后处理器机制来实现的。

 

Spring中一个非常重要的自动代理创建器DefaultAdvisorAutoProxyCreator,它可以自动的选择当前上下文中合适的增强器来使用。

DefaultAdvisorAutoProxyCreator会自动计算每个增强器中包含的切入点,考察应该将哪个增强应用于每个业务对象。

对于每个业务对象,会有若干个增强被自动地应用其上。如果没有任何增强器的切入点匹配业务对象的任何方法,该对象就不会被代理。

 

 

使用源码级元数据提供AOP之上的抽象

 

 

Spring自动代理更为简单的编码模型。

属性可以在类层面上指定,也可以在方法层面上指定 。类级别的属性将是每个方法的默认值,而方法级别的属性如果指定则会覆盖前者。超类中定义的属性也会被继承下来。

 

元数据编译 ant或者maven

 

 

你可以根据错误是否可以回复来决定程序抛出受控异常还是非受控异常。

拦截器如果要抛出异常,必须是非受控的。

 

调用方可以扑捉方面(拦截器)抛出的任何非受控异常,就当他们是由目标对象跑出来的一样

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值