Spring笔记
0. 背景
Spring Framework从诞生之日起,受到了越来越多的关注。最近,新的开源项目大多支持Spring Framework。国内目前也有专门的网站(http://spring.jactiongroup.net/)。那它为什么如此受欢迎呢?
我想最重要的是,EJB让每个人都痛恨。要编写一个EJB,需要写LocalHome, RemoteHome, Bean, LocalInterface, RemoteInterface,需要一个标准描述符,一个特殊厂商描述符(Weblogic、WebSphere都不一样),如果是Entity Bean,还需要Mapping文件。如此之多,实在麻烦。但EJB最重要的是解决Transaction问题,没有Spring之前,没有其他方法能够描述式的解决它。每个人、每个公司为了解决Transaction的问题,编程的写法都不一样,百花齐放。于是,在最需要它的时候,Spring出现了。
Spring Framework
Spring是一个解决了许多在J2EE开发中常见的问题的强大框架。 Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不是对类编程的良好习惯。Spring的架构基础是基于使用JavaBean属性的Inversion of Control容器。然而,这仅仅是完整图景中的一部分:Spring在使用IoC容器作为构建完关注所有架构层的完整解决方案方面是独一无二的。 Spring提供了唯一的数据访问抽象,包括简单和有效率的JDBC框架,极大的改进了效率并且减少了可能的错误。Spring的数据访问架构还集成了Hibernate和其他O/R mapping解决方案。Spring还提供了唯一的事务管理抽象,它能够在各种底层事务管理技术,例如JTA或者JDBC事务提供一个一致的编程模型。Spring提供了一个用标准Java语言编写的AOP框架,它给POJOs提供了声明式的事务管理和其他企业事务--如果你需要--还能实现你自己的aspects。这个框架足够强大,使得应用程序能够抛开EJB的复杂性,同时享受着和传统EJB相关的关键服务。Spring还提供了可以和IoC容器集成的强大而灵活的MVC Web框架。
1. IoC容器,Bean工厂
简单地讲,bean就是由Spring容器初始化、装配及被管理的对象,除此之外,bean就没有特别之处了。IoC容器不仅限于管理JavaBean(具有默认的(无参)构造器及setter和getter方法),它可以管理任意的类。需要用到外部配置的地方通通由我spring来管理。
尽量使用spring的模板技术(即bean的继承)。
根据经验,对所有有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。
2. Spring的事务管理
Spring的事务管理分为编程式的事务管理和声明式的事务管理。
㈠编程式的事务管理
(1)直接使用PlatformTransactionManager进行手动的commit和rollback
(2)利用TransactionTemplate
㈡声明式的事务管理
声明式的事务管理跟Spring的AOP实现一样分为两种:①ProxyFactoryBean ②自动代理
(1) ProxyFactoryBean
使用TransactionProxyFactoryBean(org.springframework.transaction.interceptor.TransactionProxyFactoryBean)为目标bean生成事务代理的配置。它必须为每一个bean都配置一个事务代理的bean。利用模板可以简化配置。
(2) 自动代理——有3种方式
① 使用BeanNameAutoProxyCreator(org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator),利用spring的aop框架配置事务代理。不需增量式配置。这种配置方式其实是依赖spring提供的bean后处理器。
② DefaultAdvisorAutoProxyCreator。同样不需增量式配置,可读性不如前者。
③ 通过annotation来实现。将所有具有@Transactional(在org.springframework.transaction.annotation的package下)注解的Bean自动配置为声明式事务支持。
在配置文件中需要用到 <tx:> 或者<aop:>命名空间
3. Spring与Struts的整合
如果整个项目与Spring进行整合,可以将Spring理解为一个性能优秀的大工厂,管理所有的bean,包括DAO组件,业务组件,还包括Struts的Action组件。跟Struts进行整合时,可以利用Spring的Ioc特性。在Struts中配置org.springframework.web.struts.ContextLoaderPlugIn。加载Spring配置文件。同时利用DelegatingRequestProcessor(org.springframework.web.struts.DelegatingRequestProcessor,该类继承自Struts的RequestProcessor类),将action的请求转发到由Spring管理的action bean去处理。这样在所有的java代码中就不需要显式调用Spring的Context来获取bean。
Spring跟webwork的集成由WebWork框架提供,跟struts2的集成也是由struts2框架提供的(加入struts2-spring-plugin-2.0.11.jar)。
4. Spring提供了几种Resource的实现
在Spring的XML配置文件中,注入的Resource资源总是有一个字符串来表示的.Spring根据字符串(例如classpath:config.xml或者http://java.sun.com或者file:///c:/windows/或者直接的test.txt)来判断应该如何创建相应的Resource。
最常用的Resource实现是:
(1)UrlResource
(2)ClassPathResource
(3)FileSystemResource
5. 有了Spring,可以让接口应尽量最小化这一特性得到充分发挥。
6. Spring Framework拥有自己的AOP框架,这个框架在概念上是十分容易理解的,而且它成功地实现了在Java企业级开发中对AOP需求的80%左右。开发手册中还描述了Spring与AspectJ的集成方法。 (当前来说,AspectJ是Java企业级开发领域中特性最多、最成熟的AOP实现。)
7. 依赖注入的高级特性:
Spring提供了3中工厂模式Bean的配置——
(1)静态工厂 XML配置中要定义factory-method
(2)实例工厂 XML配置中要定义bean实例及factory-method
(3)FactoryBean FactoryBean指的是实现了Spring的FactoryBean接口的Bean。
BeanPostProcessor使我们有能力在Spring容器对Bean初始化前后对所有的Bean进行检查和修改,而BeanFactoryPostProcessor允许我们在Spring容器对所有的Bean初始化之前对Bean的定义做修改。
Lookup方法注入。
8. 使用Spring的org.springframework.beans.factory.config.PropertyPlaceholderConfigurer,可以根据指定Porperties文件的属性值进行替换。
9. Http远程调用协议
Spring本身还提供了一个Http远程调用协议,我们暂且称之为HTTP Invoker。HTTP Invoker使用Java标准的序列化机制(因此仅适用于Java平台之间的通讯),通过HTTP协议来实现远程调用。
10. Acegi及安全
Acegi安全框架通过基于Filter的URL过滤实现了针对Web资源的保护,通过基于AOP拦截的机制实现了针对组件的方法级别的保护。这两者在实际项目中的应用都非常广泛。
JAAS(Java Authentication and Authorization Service) —— Java验证与授权服务。
11. AOP
AOP最常见的应用就在于事务管理、日志记录、权限检查这几个方面(也称为切面,Aspect)。这些系统级关注点非常容易通过AOP实现横切。
AOP并非一种全新的技术,他仅仅是使用了更简单的、更优雅的设计来实现传统的Proxy、Decorator等模式。
在Spring中,如果针对接口的代理(推荐的也是默认情况下),则采用JDK动态代理机制来实现AOP。如果针对具体类的代理,则将使用CGLIB运行时的动态字节码生成技术来实现AOP。
Spring的AOP实现有两种:①ProxyFactoryBean ②自动代理
一. ProxyFactoryBean是利用org.springframework.aop.framework.ProxyFactoryBean,注入目标对象,然后生成AOP代理。
二. Spring的自动代理实际上是由BanPostProcessor实现的。在容器载入XML配置之后,将所有需要实现代理的目标Bean全部修改为代理Bean,而id不变。这样客户端就无法直接直接访问目标Bean了。
Spring提供了几种常用的AOP的自动代理:
1)BeanNameAutoProxyCreator (org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator)
2)DefaultAdvisorAutoProxyCreator(org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator)
3)通过AspectJ的annotation来配置(@Aspect @Pointcut @Before 等标注)
12. AOP的一些常用术语:
Aspect—— 切面,或称系统的关注点。例如安全检查、日志记录、事物控制。在AspectJ的annotation中(在org.aspectj.lang.annotation的package下),可以将一个实现处理该系统关注点的类标注上@Aspect.(例如LoggerAspect),和直接实现Advice接口来实现一个类对应一种Advice不同,一个切面类可以包含多个Advice和Pointcut,每个Advice和Pointcut都是由一个独立的方法加上特定的annotation来表示。
Pointcut—— 切入点。一般是描述织入目标对象的哪些连接点。例如通过通配符insert*来描述织入业务实现类的insert开头的方法。在AspectJ的annotation中可以通过类似
@Pointcut("execution(* example.chapter4.UserService.login(..))")
来描述Pointcut.
Advice—— 可译为增强。常见的有BeforeAdvice,AfterReturningAdvice,ThrowsAdvice等。本质上就是一个拦截器,可以拦截方法调用,然后执行自己的一段代码来增强应用程序的逻辑。AspectJ的annotation中,有@Before,@AfterReturning,@AfterThrowing,@Around等标注在具体执行增强的方法标注上。
Interceptor——Spring所定义的。Interceptro(拦截器),是Advice的一种实现。常见的有MethodInterceptor,ConstructorInterceptor.
Advisor—— Spring所定义的。Advisor必须包含一个Advice。而常用的PointcutAdvisor包含一个Advice还有一个Pointcut.
Weaving—— 动作。就是说将切面整合到程序的执行流程中。
13. 在Java平台上,对于AOP模块的织入,有3种方式:
1、运行时织入-即在java运行的过程中,使用Java提供代理来实现织入。根据代理产生方式的不同,运行时织入又可以进一步分为J2SE动态代理及动态字节码生成两种方式。由于J2SE动态代理只能代理接口,因此,需要借助于一些动态字节码生成器(例如CGLIB)来实现对类的动态代理。大多数AOP实现都是采用这种运行时织入的方式,包括Spring。
2、类加载器织入-指通过自定义的类加载器,在虚拟机JVM加载字节码的时候进行织入,比如AspectWerkz(已并入AspecJ)及JBoss就使用这种方式。
3、编译器织入-使用专门的编译器来编译包括切面模块在内的整个应用程序,在编译的过程中实现织入,这种织入是功能最强大的。编译器织入的AOP实现一般都是基于语言扩展的方式,即通过对标准java语言进行一些简单的扩展,加入一些专用于处理AOP模块的关键字,定义一套语言规范,通过这套语言规范来开发切面模块,使用自己的编译器来生成java字节码。AspectJ主要就是是使用这种织入方式。
14. Spring跟Servlet的结合
通过在web.xml中定义servlet——org.springframework.web.servlet.DispatcherServlet。便可以通过实现org.springframework.web.servlet.mvc.Controller接口来定义简便的Servlet Bean。