日期:2014-05-19  浏览次数:20759 次

《J2EE development without EJB》读书笔记(四)



第7章 Spring框架简介(IOC)
轻量级容器一个重要出发点就是消除J2EE应用中众多自制的工厂和Singleton。
对于服务型对象,Singleton模式足够了。
工厂Bean:FactoryBean本身是在bean工厂中定义的一个bean,同时又是用于创建另一个对象的工厂。实际注册到bean工厂中的是FactoryBean创建的对象,而不是FactoryBean本身。
JndiObjectFactoryBean:通过JNDI查找而获得对象(使用EJB等JNDI树上的资源,EJB结合Spring共同使用)
LocalSessionFactoryBean:创建本地装配的Hibernate SessionFactory
ProxyFactoryBean:经典Spring AOP使用其创建代理
除非你使用EJB,否则基本上不应该在JNDI中保存持久层工具的连接工厂。这样的连接工厂是特定于应用程序的,并不适合在服务器级别共享。使用JNDI也不会带来集群方面的好处:集群环境下的资源锁通常是通过数据库锁或集群缓存来实现的,根本不需要将连接工厂放入JNDI中。
***********************************************
第8章 基于AOP概念的声明性中间件 
衡量OOP成功与否的标准就是它在多大程度上避免了代码重复。而有些横切性的问题导致的代码重复让OO显得力不从心,继承也是爱莫能助。传统EJB使用代码生成解决这种问题,由EJB容器在部署时负责生成子类,添加重复的代码,引入横切行为。虽然开发者避免编写重复代码,但是部署过于复杂,而且只有EJB才可享受这种待遇,另外EJB容器一开始就规定了横切问题导致的不灵活,都使代码生成不足以满足我们的需要。
AOP提供了OO层级模型无法提供的新视角-将横切性问题以一种更加通用的方式模块化,从而提高程序的模块化程度。我们可以使用的策略:代码生成+预编译(EJB)、AOP语言(AspectJ)、动态字节码生成(CGlib)、J2SE动态代理(Spring AOP)。
我们不仅从领域问题中划分出对象层级,还划分出一些横切性的关注点,彻底避免了代码重复。

AOP中的几个概念:
1、关注点(concern)一个特定的问题、概念、或是应用程序的兴趣区间,比如:安全性、事务管理等
2、横切关注点(crosscutting concern)如果一个关注点的实现代码散落在很多个类或方法之中,这样的关注点就是横切关注点。
3、连接点(join point)程序执行过程中的一点,比如:方法调用、字段访问、异常抛出
4、增强(advice)在特定连接点执行的动作。
前增强(before,pre)在连接点调用之前,首先调用增强。
后增强(after,post)在连接点调用之后,再调用增强。在AspectJ中,后增强又分为三种:
  返回后增强:在调用成功完成(没有异常抛出)之后
  抛出后增强/抛出增强:在抛出某种特定类型(或其子类型)的异常之后
  后增强:在连接点的任何调用之后,不管调用是否抛出异常
环绕增强(around)这类增强可以控制执行流程。除了完成本身的工作之外,它还需要负责主动调用连接点,促使真实的操作发生。
注:环绕增强可以用于实现所有其它类型的增强,只要主动促使实际操作发生即可。从可用性的角度出发,建议选择功能最弱且目的最明确的增强,避免出现错误。比如:前增强和后增强都不会改变连接点的返回值,而环绕增强则有可能。
5、切入点(pointcut)一组连接点的总称,用于指定某个增强应该在何时被调用。
静态标准切入点:根据部署阶段的信息选择增强
动态标准切入点:根据运行时的信息选择增强
6、引介(introduction)为一个现有的Java类或接口添加方法或字段。
7、混入继承(mixin inheritance)一个“混入类”封装了一组功能,这组功能可以被“混入”到现有的类当中,并且无需求助于传统的继承手段。在AOP这里,混入是通过引介来实现的。在Java语言中,通过混入来模拟“多继承”。
8、织入(weaving)将方面整合到完整的执行流程(或完整的类,此时被织入的便是引介)中。
当执行流程进展到连接点时,增强会首先接管流程控制权。当增强允许执行流程继续前进,执行真正的方法调用或字段访问时,我们就说这次操作发生了。
以下几个概念不是出自于AspectJ:
9、拦截器(interceptor)很多AOP框架(如Spring,但不包含AspectJ)用它实现字段和方法的拦截。随之而来的就是在连接点处挂接一条拦截器链(interceptor chain),链条上的每个拦截器通常会调用下一个拦截器。拦截是一种AOP的实现策略。
10、AOP代理(AOP proxy)被增强的对象引用。(AspectJ的增强是直接针对Java类的字节码进行的,因此没有这样的概念。但是对于基于拦截的AOP框架,AOP代理是整个框架的基石,AOP代理可能是使用J2SE的动态代理,或借助字节码操作工具生成。)
11、目标对象(target object)位于拦截器链末端的对象实例。当然,这个概念也是只存在于基于拦截机制的AOP框架之中。有时拦截器链上也会没有目标对象:这种情况很罕见,整个预期行为就是通过拦截器的组合来完成的,比如:一个对象可能有多个“混入”构成。(像AspectJ这种在编译期完成织入的AOP实现没有明确的“目标对象”的概念。目标对象的字节码就是直接包含了所有的增强。)
几个没有完全解决AOP问题的设计模式:Decorator(装饰器)、Observer(观察者)、Chain of Responsilility(责任链)
注:使用OO的设计模式不可能做到既保持被增强方法的强类型性,又不必自己动手为每个方法调用编写转发代码。
EJB如何解决类似AOP问题
EJB容器必须拦截方法的调用,以便插入企业级服务。具体拦截机制有两种(织入策略):动态代理和代码生成。不同的容器实现的策略不相同。
AOP各种实现策略
1、J2SE动态代理
优点:标准Java语言特性
缺点:只能针对接口进行代理、反射调用的额外开销
Spring默认使用动态代理
2、动态字节码生成(dynamic byte code generation)
基于Java反射和类装载机制,针对指定的类动态生成一个子类,并覆盖其中的方法,从而实现方法的拦截。
优点:可以针对类进行代理
缺点:对于final类或者是final方法无法提供代理
Spring对于类的代理就是使用CGLIB,Hibernate也在使用。
3、Java代码生成
生成新的Java源码,在其中执行横切性的代码。传统EJB的实现方式,不再流行。
4、使用定制的类加载器
通过定义一个自制的类加载器,可以在一个类被加载时自动对其进行增强。这样即便用户使用new构造实例,增强也是生效的。JBoss和AspectWerkz都采用这种做法,具体增强信息则是在运行时从XML配置文件中读取。
这种做法风险较大,它偏离了Java的标准,而且在某些应用服务器中,由于需要控制整个类加载的层级体系,因此这种做法会出现问题。
5、语言扩展
让编程语言同时支持AOP和OOP。AspectJ就针对Java进行了扩展,提供自己的编译器。

Spring AOP
增强器(advisor)是Spring AOP中提出的更高级的概念,它包括一个是增强、一个用于说明“在何处进行增强”的切入点。增强器(advisor)完美的模块化了一个方面(aspect)。
引介是通过IntroductionAdvisor对象实现的。但是不同于其它增强器,引介增强器不包含切入点,因为引介是在类的层面上进行的,方法级的匹配没有任何意义。
Spring不支持字段的拦截,这样Spring有意而为之,主要是考虑性能问题。Spring的真正目标是鼓励用户从Spring容器中获得业务对象,从而获得良好的应用结构。
Spring AOP必须要依赖Spring IOC容器,没有提供强类型检查。
自动代理就是通过Bean后置处理器机制实现的。只要配置好,机制就允许Spring容器透明地对任何业务对象进行代理。对于每个业务对象,如果有增强器,就会被代理,而没有任何增强器的切入点匹配业务对象的任何方法,该对象就不会被代理。这样调用者或依赖对象绝不会拿到未经增强的对象。

AOP风险
1