Your SlideShare is downloading. ×
Spring框架
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Spring框架

2,009
views

Published on

Spring框架 概述

Spring框架 概述

Published in: Technology, Education

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
2,009
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
37
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Spring 简介与入门
  • 2. Spring 简介
    • 与 Hibernate 、 Struts 一样, Spring 也是一个开源项目,它的作者是 Rod Johnson ,官方网站是 http://www.springframework.org/ 。
    • Spring 的基础思想来源于 Rod Johnson 的一本著名的 j2ee 书籍: Expert One-on-One J2EE Design and Development 。在这本书中, Rod Johnson 列举 EJB 的种种问题,并提出了相应的解决办法。
    • 从那时起,人们对于 EJB 的狂热追捧才算结束,转而进入更理性的时代。
  • 3. Spring 简介
    • Rod Johnson 是悉尼大学博士,
    •  猜猜他的专业是什么?
    • Rod Johnson 在开发出 Spring
    •  之前,主要从事项目开发咨询
    •  与培训工作。在 Spring 被广泛认可之后,创办了 interface21 公司,致力于 Spring 咨询与培训
    • Rod Johnson 还是 JDO2.0 和 Servlet2.4 专家组成员。
  • 4. Spring 简介
    • Spring 核心技术包括两个方面,一是控制反转( Inversion of Control, IoC ),另一个是面向方面编程( Aspect Oriented Programming, AOP )。
    • Spring 囊括了十分丰富的内容,包括表述层、数据层,它提供了许多原来只有 EJB 才能提供的功能(如宣称式的事务管理),但 Spring 又无须运行在 EJB 容器上。
    • 无论 Spring 涉足到哪一个领域,使用的都是简单的 JavaBean ,一般无须再实现复杂的接口。
  • 5. Spring 简介
  • 6. Spring 简介
  • 7. Spring 技术基础
    • Spring 的核心是 IoC 和 AOP ,它们都是由 Java 原有技术发展而来的。
    • IoC 技术是通过 Java 的反射机制以及 JavaBean 的自省机制实现的
    • AOP 技术是依赖代理模式实现的, JFC 中提供了对代理模式的内在支持, Spring 也是通过这种技术实现的。
    • 为了能够理解 Spring 的 IoC 机制,下面对反射机制和自省机制做简单介绍。
  • 8. 反射机制
    • Java 的反射机制允许程序在运行时动态加载对象,并且动态地调用其中的方法。
    • JFC 中的 java.lang.reflect 包便提供了这种支持,主要是通过 java.lang.Class 、 java.lang.reflect.Method 、 Field 、 Constuctor 等类完成这项工作的。
    • 例如,如果有下面的方法:
    • Object myInvoke(String class,
    • String methodName,
    • Objec[] args)
    • 实现动态调用某一类的某一方法,该如何实现?
  • 9. 反射机制
    • public Object myInvoke(String className, String methodName, Object args[]) {
    • Object results = null;
    • try {
    • Class clazz = Class.forName(className);
    • Method method = null;
    • for (int i = 0; i < clazz.getMethods().length; i++) {
    • method = clazz.getMethods()[i];
    • if(methodName.equals(method.getName())) {
    • results = method.invoke(clazz.newInstance(), args);
    • break;
    • }
    • }
    • } catch (Exception e) {
    • e.printStackTrace();
    • }
    • return results;
    • }
  • 10. 反射机制
    • 使用时指明类名和方法名:
    • class SomeToBeInvoke {
    • public int calculate(int i) {
    • return i*i;
    • }
    • }
    • ReflectDemo demo = new ReflectDemo();
    • Object obj = demo.myInvoke(&quot;SomeToBeInvoke&quot;,
    • &quot;calculate&quot;,
    • new Object[]{new Integer(6)});
    • System.out.println(obj);
  • 11. Class 类
    • java.lang.Class 代表一个类,可以通过三种方式得到 Class 的实例:
    • Object.getClass()
    • Class.forName()
    • 直接用类名点 class ,如: A.class
    • Class 的实例代表的是类,不代表类的实例。即 Class c = A.class , c 是类而不是实例。如果创建实例,可以调用 newInstance() 方法。
  • 12. Class 类
    • 可以通过 Class 加载类并了解类的内部结构:
    • 获取构造函数: Constructor getConstructor(Class[] parameterTypes) Constructor[] getConstructors()
    • 获取方法: Method getMethod(String name, Class[] parameterTypes) Method[] getMethods()
    • 获取属性: Field getField(String name) Field[] getFields()
    • 检查特性: Class[] getInterfaces() 、 Package getPackage() 、 boolean isArray() 、 boolean isInterface()
  • 13. Field 类
    • java.lang.reflect.Field 代表属性,是 java.lang.reflect.AccessibleObject 的子类,故可以调用其 setAccessible 方法访问 private 类型的属性。
    • Field 中声明了多个 getter 和 setter 方法,可以设置属性的值。
  • 14. Method 类
    • java.lang.reflect.Method 代表类中的方法,它也是 java.lang.reflect.AccessibleObject 的子类,可以通过 setAccessible 访问 private 类型方法。
    • 可以通过调用 Object invoke(Object obj, Object[] args) 方法,间接调用对象方法。
  • 15. Contructor 类
    • java.lang.reflect.Constructor 代表构造函数,是 java.lang.reflect.AccessibleObject 的子类,可以通过 setAccessible 访问 private 类型方法。
    • 可以通过 Object newInstance(Object[] initargs 方法调用构造函数,创建新实例。
  • 16. JavaBean 自省机制
    • JavaBean 的属性一般都具有 getter 方法和 setter 方法,通过这些方法可以更改或读取 JavaBean 属性。
    • JavaBean 具有的自省机制可以在不知道 JavaBean 都有哪些属性的情况下,设置它们的值。
  • 17. Introspector
    • 自省机制是使用 Introspector 实现的。
    • Introspector 的方法大部分都是静态的,可以直接调用,如 getBeanInfo(Class beanClass) 可以得到一个 JavaBean 的 BeanInfo 实例。
    • BeanInfo 实例包含了一个 JavaBean 类属性和方法的信息。如:
    • BeanDescriptor getBeanDescriptor()
    • MethodDescriptor [] getMethodDescriptors()
    • PropertyDescriptor [] getPropertyDescriptors()
  • 18. PropertyDescriptor
    • PropertyDescriptor 代表了属性,可以通过它得到属性的 getter 方法和 setter 方法。即 :
    • Method getReadMethod()
    • Method getWriteMethod()
    • 通常在不知道 JavaBean 属性时,如果设置 JavaBean 属性就采用 PropertyDescriptor 。 PropertyDescriptor(String propertyName, Class beanClass)
  • 19.
    • 所谓代理模式即是由代理对象接管对象访问,用户在使用时感觉是在原始对象操作,但实际是通过代理对象访问的原始对象。
    • Java 为代理模式提供了内置的支持,这是通过 java.lang.reflect.Proxy 以及 java.lang.reflect. InvocationHandler 实现的。
    代理( Proxy )模式
  • 20. 代理( Proxy )模式
    • 所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。
    • 在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
  • 21. 代理模式的结构
  • 22. 代理模式的角色
    • 抽象主题角色:声明了真实主题和代理主题的共同接口,这样在任何可用真实主题的地方都可以使用代理主题。
    • 代理主题角色:代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真实主题对象,代理角色通常在将客户端调用传递给真实的主题之前或之后,都要执行某个操作。
    • 真实主题角色:定义了代理角色所代表的真实对象。
  • 23. 代理模式的时序
  • 24. 装配 Bean
  • 25. IoC 与 Bean 装配
    • 在 Spring 中,对象间的协作是通过 IoC 机制完成的。
    • 反向控制也叫依赖注入( Dependency Injection , DI ),简单来说就是将 JavaBean 需要的对象通过配置文件加载进来。
    • Spring 提供了两种装配 Bean 的容器,一是 BeanFactoy ,另一个是 ApplicationContext 。
    • 两者做为容器,所有的 Bean 都应该通过容器装配,而容器也知道自己都装配了哪些 Bean 。
  • 26. Bean 容器
    • ApplicationContext 与 BeanFactory 都是接口, ApplicationContext 是由 BeanFactory 接口扩展而来,它增强了 BeanFactory 的功能。
    • Bean 容器能够加载的对象并不一定是严格遵循 JavaBeans 规范的 Java 类,任何可实例化的类都可以通过 Spring Bean 容器加载进来。通常称这些类为 POJO 。
    • 要记住, BeanFactory 不仅仅只具备实例化 Bean 的功能,它还知道所有的 Bean ,可以配置和管理它们。
  • 27. BeanFactory
    • 以下是 BeanFactory 声明的方法,都是与 Bean 装配相关的:
    • boolean containsBean(String name)
    • String[] getAliases(String name)
    • Object getBean(String name)
    • Object getBean(String name, Class requiredType)
    • Class getType(String name)
    • boolean isSingleton(String name)
  • 28. BeanFactory
    • Spring 给出一些 BeanFactory 的实现类,其中最为常用的是 XmlBeanFactory 。
    • 1 、通过文件系统
    • Resource res = new FileSystemResource(&quot;beans.xml&quot;);
    • XmlBeanFactory factory = new XmlBeanFactory(res);
    • 2 、通过类路径
    • ClassPathResource res = new ClassPathResource(&quot;beans.xml&quot;);
    • XmlBeanFactory factory = new XmlBeanFactory(res);
    • 3 、通过 ApplicationContext 加载
    • ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
    • new String[] {&quot;applicationContext.xml&quot;, &quot;applicationContext-part2.xml&quot;});
    • BeanFactory factory = (BeanFactory) appContext;
  • 29. Resource
    • 创建 XmlBeanFactory 时需要以 Resource 作为构造函数的参数。
    • Resource 接口位于 org.springframework.core.io 包内,通过 XmlBeanFactory 创建 BeanFactory 时都要使用到这个接口。
    • Resource 代表了所有可以访问的底层资源,如文件系统、类路径、 URL 等等。
  • 30. Resource
    • 实现了 Resource 接口的类包括:
    • AbstractResource,
    • ByteArrayResource, -- byte[]
    • ClassPathResource, -- String path
    • DescriptiveResource, -- String description 不实际指向资源,只包含描述信息
    • FileSystemResource, -- File , or, String path
    • InputStreamResource, -- InputStream
    • ServletContextResource, -- ServletContext, String
    • UrlResource -- URL , or , String path
  • 31. Resource
    • Resource 中定义了以下方法:
    • Resource createRelative(String relativePath)
    • boolean exists()
    • String getDescription()
    • File getFile()
    • String getFilename()
    • URL getURL()
    • boolean isOpen()
  • 32. 装配 Bean
    • 通常可以通过三种方式装配 Bean
    • 通过 setter 方法
    • 通过构造函数
    • 自动装配
    • 其中,使用 setter 方法装配 Bean 是最为常用的。
  • 33. 装配 Bean
    • 无论使用 BeanFactory 还是 Applicationcontext 均可以视之为容器,使用的 Bean 必须向容器注册。
    • 注册是通过在配置文件中加入 Bean 声明:
    • <beans>
    • <bean id=“first” class=“mybeans.FirstBean”/>
    • <bean id=“second&quot; class=“mybeans.Second”/>
    • </beans>
    • 注册后的 Bean 是被容器识别的,容器可以协调他们之间的关系
  • 34. 装配 Bean
    • <!ELEMENT bean (
    • description?,
    • (constructor-arg |
    • property |
    • lookup-method |
    • replaced-method)*
    • )>
  • 35. 原型或单例
    • 如下代码的执行结果是什么?
    • FirstBean bean = (FirstBean)factory.getBean(&quot;my&quot;);
    • FirstBean bean1 = (FirstBean)factory.getBean(&quot;my&quot;);
    • System.out.println(bean==bean1);
    • 结果依赖于 bean 元素的 singleton 属性,如果设置 true ,则以单例模式加载 bean ,则永远指向同一个 bean ;反之则每次实例化一个。
    • 也即在单例模式下, BeanFactory 维护所有的 bean
  • 36. 原型或单例
    • BeanFactory 维护所有单例 bean ,也即维护了对单例 bean 的引用,因此 factory 只知道创建单例 bean 的数目,而无从知晓原型 bean 。
    • 原型 bean 创建后即脱离了容器,容器不维护对 bean 的引用,因此也无法再管理 bean 。
    • 不是绝对必要,不要使用原型,而应尽可能使用单例。
  • 37. 延迟加载
    • 如下代码执行的结果是什么?
    • System.out.println(&quot;before loading&quot;);
    • FirstBean bean = (FirstBean)factory.getBean(&quot;my&quot;);
    • System.out.println(“after loading”);
    • 在 bean 的构造函数中,包含:
    • System.out.println(“bean init”);
    • 结果依赖于 bean 的 lazy-init 属性,如果设置为 true ,则在第一次加载该 bean 时初始化;否则在初始化容器时就加载所有 bean 。
    • 延迟加载仅在 bean 单例模式下起作用 。
  • 38. 初始化与清理
    • 在许多情况下,需要在对象加载后立即初始化资源,而在删除对象前先清理资源
    • 在 spring 中,提供了两种方式实现初始化和清理工作。
    • 通过设置 bean 的 init-method 和 destroy-method 指定初始与清理方法
    • 通过实现 InitializingBean 及 DisposableBean 接口,由容器在加载与删除 bean 时自动调用。
  • 39. 初始化与清理
    • <bean id=&quot;first&quot; class=&quot;mybeans.FirstBean&quot; init-method=&quot;init&quot; destroy-method=&quot;destroy&quot; >
    • <property name=&quot;message&quot;>
    • <value>Hi, Rod Johnson</value>
    • </property>
    • </bean>
    • 可以通过 destroySingletons 方法删除所有单例 bean
    • 原型 bean 在创建后即脱离 BeanFactory 的维护,所以只能调用初始化方法,而不能做清理工作。
  • 40. 初始化与清理
    • 通过 InitializingBean 和 DisposableBean.
    • InitializingBean 接口中仅定义了一个方法,即 void afterPropertiesSet ()
    • DisposableBean 接口也是这样,方法为:  void destroy ()
    • 这两个接口都位于 org.springframework.beans.factory 包中,须向容器注册 id 以及 class 。
  • 41. 初始化与清理
    • 初始化与清理的次序
    • 无论是哪种初始化方式,都是在 bean 构造完毕,并且 属性已经注入 到对象中后才执行的。
    • 初始化时, InitializingBean 定义的初始化方法 先于 init-method 中指定的方法。
    • 清理时, DisposableBean 定义的清理方法 先于 destroy-method 指定的方法。
  • 42. Setter 装配
    • 在配置文件中, <bean> 元素的 <property> 元素 指明了使用属性的 setter 方法注入依赖。
    • <!ELEMENT property (
    • description?,
    • (bean | ref | idref | value | null | list | set | map | props)?
    • )>
    • <!ATTLIST property name CDATA #REQUIRED>
    • <!ATTLIST property ref CDATA #IMPLIED>
    • <!ATTLIST property value CDATA #IMPLIED>
    • Setter 装配要求 bean 中必须与相应的 setter 方法,即使没有这个属性
  • 43. Setter 装配- 装配种类
    • 可以通过 setter 方法加载以下类型的属性:
    • 基本类型
    • Bean 类型
    • 内部 bean 类型
    • 集合类型
    • 设置空值
  • 44. Setter 装配-基本类型
    • 装配基本类型:
    • 包括八种基本类型及它们的包装类,还有 String 类型。
    • 不必关心具体类型, spring 可以通过反射机制了解到属性的类型信息
    • 可以通过 <property> 的子元素 <value> 来设置基本类型的值,也可以通过其属性 value 来设置,效果完全相同。
  • 45. Setter 装配-基本类型
    • <bean id=&quot;first&quot; class=&quot;mybeans.FirstBean&quot; >
    • <property name=&quot;message&quot;>
    • <value>Hi, Rod Johnson</value>
    • </property>
    • <property name=&quot;age&quot; value=&quot;1&quot; />
    • </bean>
    • 注意不能同时使用 value 子元素和 value 属性
  • 46. Setter 装配- bean 类型
    • 装配 bean 类型属性:
    • 只有通过配置文件向容器注册的 bean 才能通过注入机制设置到其它 bean 的属性上。
    • 使用 <ref> 子元素或 ref 属性设置
    • Spring 即是通过这种方式建立起 bean 间的依赖关系,实现强大的 bean 管理功能。
  • 47. Setter 装配- bean 类型
    • <bean id=&quot;first&quot; class=&quot;mybeans.FirstBean&quot;>
    • <property name=&quot;message&quot;>
    • <value>Hi, Rod Johnson</value>
    • </property>
    • <property name=&quot;age&quot; value=&quot;1&quot; />
    • <property name=&quot;second&quot; ref=&quot;second&quot;/>
    • </bean>
    • <bean id=“second” class=“mybeans.SecondBean” >
    • <property name=&quot;first&quot;>
    • <ref bean=&quot;first&quot;/>
    • </property>
    • </bean>
  • 48. Setter 装配- bean 类型
    • 内部 Bean
    • <bean id=&quot;outer&quot; class=&quot;...&quot;>
    • <property name=&quot;target&quot;>
    • <bean class=&quot;com.mycompany.PersonImpl&quot;>
    • <property name=&quot;name&quot;>
    • <value>Tony</value>
    • </property>
    • </bean>
    • </property>
    • </bean>
  • 49. Setter 装配-集合类型
    • Spring 支持以下四种集合的装配:
    • <list> -- java.util.List
    • <set> -- java.util.Set
    • <map> -- java.util.Map
    • <props> -- java.util.Properties
  • 50. Setter 装配- list 集合
    • <property name=&quot;someList&quot;>
    • <list>
    • <value>someValue</value>
    • <ref bean=&quot;myDataSource&quot;/>
    • <list>
    • <value>anyValue</value>
    • </list>
    • </list>
    • </property>
  • 51. Setter 装配- set 集合
    • <property name=&quot;someSet&quot;>
    • <set>
    • <value>just some string</value>
    • <ref bean=&quot;myDataSource&quot;/>
    • </set>
    • </property>
  • 52. Setter 装配- map 集合
    • <property name=&quot;someMap&quot;>
    • <map>
    • <entry>
    • <key><value>yup an entry</value></key>
    • <value>just some string</value>
    • </entry>
    • <entry>
    • <key><value>yup a ref</value></key>
    • <ref bean=&quot;myDataSource&quot;/>
    • </entry>
    • </map>
    • </property>
  • 53. Setter 装配- props 集合
    • <property name=&quot;people&quot;>
    • <props>
    • <prop key=&quot;HarryPotter&quot;>
    • The magic property
    • </prop>
    • <prop key=&quot;JerrySeinfeld&quot;>
    • The funny property
    • </prop>
    • </props>
    • </property>
  • 54. Setter 装配-设置 null
    • 如果希望将属性设置为空,使用以下方法不能达到目的:
    • <property name=&quot;age&quot; >
    • <value></value>
    • </property>
    • 应该按如下方式注入:
    • <property name=&quot;age&quot; >
    • <null/>
    • </property>
    • 属性必须为 Object
  • 55. 构造装配
    • 构造装配通过构造函数装配 bean 属性,一般在以下情况下使用:
    • 属性没有 setter 方法,是只读属性
    • 属性只需要设置一次,以后就不会再更改
    • 一般使用构造装配只装配少量属性
    • 构造装配下,构造函数中应该包含有需要装配的属性
  • 56. 构造装配
    • <bean id=&quot;first&quot; class=&quot;mybeans.FirstBean&quot;>
    • <constructor-arg>
    • <value>http://www.sohu.com</value>
    • </constructor-arg>
    • <constructor-arg>
    • <value>http://localhost:8080</value>
    • </constructor-arg>
    • <property name=&quot;age&quot; value=&quot;1&quot; />
    • </bean>
    • 多个参数时使用多个 constructor-arg 指定,出现 次序决定了参数次序,或者使用 index 属性指定
  • 57. 自动装配
    • 可以通过 spring 框架自动为 bean 装配属性。
    • 自动装配只能装配 bean 类型,即取代 ref 元素。
    • 使用自动装配只需在 bean 元素中加入属性 autowire ,自动装配可被手动装配覆盖。
    • 也可以选择在 beans 中加入 default-autowire 属性,为所有 bean 设置默认自动装配。
  • 58. 自动装配类型
    • “ no“ -不使用自动装配, spring 推荐。
    • “ byName” -依据名称或 ID 装配 bean ,如果没有找到,则不装配
    • “ byType” -依据类型自动装配,如果存在两个以上同种类型,则抛出异常。
    • “ constructor” -依据当前 bean 构造函数装配,查找与构造函数参数 同类型 bean
    • “ autodetect” -自动检测,先通过 constructor ,再使用 byType
  • 59. 装配 Bean
    • 通过 BeanFactory 获取 Bean 与直接 new 一个 Bean 是完全不同的。
    • 通过 BeanFactory 获取的 bean 能将所有依赖注入到 bean 中,属性的值会依设置而定。
    • New 出来的 bean 属性值必须主动设置。
    • 在需要使用 spring 框架情况下,所有 bean 都应该由容器来管理。
  • 60. ApplicationContext
    • ApplicationContext 与 BeanFactory 的作用相类似,都起到装配、管理 Bean 的作用。
    • 不同的是, ApplicationContext 在此基础上增强了 BeanFactory 的功能,这包括国际化、加载资源、发布事件等等。
    • 实现了 ApplicationContext 接口的类包括:
    • 1 、 ClassPathXmlApplicationContext
    • 2 、 FileSystemXmlApplicationContext
    • 3 、 GenericApplicationContext
    • 4 、 GenericWebApplicationContext
    • 5 、 StaticApplicationContext
    • 6 、 StaticWebApplicationContext
    • 7 、 XmlWebApplicationContext
    • 它们的使用方法与 BeanFactory 基本相同
  • 61. ApplicationContext
    • ApplicationContext 接口由以下接口扩展而来:
    • ListableBeanFactory -可以列出所有 bean
    • HierarchicalBeanFactory -可以找到父工厂
    • MessageSource -处理国际化
    • ApplicationEventPublisher -处理事件
    • ResourcePatternResolver -资源解析
  • 62. 面向切面- AOP
  • 63. AOP 简介
    • AOP 最初由 Gregor Kiczales 在施乐的 Palo Alto 研究中心领导的一个研究小组于 1997 年提出。
    • 目前,宣称能够支持 AOP 的项目已达近百种, Java 语言的实现也有 20 多种,其中最为完善的是 AspectJ 。这是由 Gregor Kiczales 领导的小组完成的。
  • 64. AOP 简介
    • AOP 是 OOP 的延续,是 Aspect Oriented Programming 的缩写,意思是面向方面编程。
    • 它将分布在各个类中具有相同功能的代码片段整合到一起,由单独的功能模块完成,不仅减少了代码的重复量,降低了耦合,也提高了代码的可维护性。
    • 不要认为 AOP 会取代 OOP ,它只是 OOP 的补充。但就像当年的 OOP 一样,它很可能引发一场软件产业的革命。
  • 65. AOP 简介
  • 66. AOP 术语
    • 切面( Aspect ):从对象中抽取出来的交叉功能模块
    • 通知( Adivice ):切面的具体实现
    • 连接点( Joinpoint ):可以插入方法的地方
    • 切入点( Pointcut ):连接点的集合
    • 引入( Introduction ):为已经存在的类添加新方法和属性
  • 67. AOP 术语
    • 目标对象( Target Object ):
    • 被通知的对象
    • 代理( AOP Proxy ):
    • 由 AOP 框架创建的目标对象的代理对象
    • 织入( Weaving ):
    • 将通知与目标对象结合在一起,生成新的代码片段的过程
  • 68. AOP 实现技术
    • 目前,人们使用传统语言对核心业务进行编程,对横切面的功能模块则使用面向切面的编程语言。
    • 面向切面的编程语言可以是已有编程语言的扩展,如 AspectJ , AspectC++ , AspectC , AspectC# , Apostle 等,或是一种新的语言
    • Java 语言可以使用反射( Reflection ),基于动态代理( Dynamic Proxy )或其它机制的拦截框架,基于元数据( Metadata )的操作,以及类载入时对字节码的操作等来实现 AOP 。
  • 69. AOP 实现技术
    • Spring 使用两种机制实现 AOP 技术,一是使用 java 的动态代理,即 java.lang.reflect.Proxy 类创建代理。
    • 二是使用 CGLIB 库自动生成目标对象的子类,同时织入通知。
    • 动态代理要求目标对象必须要实现接口(只有这样才能创建代理),而 CGLIB 则没有这种限制。
  • 70. AOP 实现技术
    • 由于目前 AOP 还没有完全的统一标准,因此实现出来的 AOP 框架也是多种多样的,为此人们成立了一个 AOP 联盟,用于统一这种混乱局面
    • Aop Alliance 是由多个 AOP 项目组成的组织,定义一套 AOP 标准的 Java 接口,以方便各种 AOP 框架可以互通。
    • Spring 也是以这套接口为基础的。
  • 71. AOP 快速入门
    • 背景:课程在开课前应该向任课老师发出上课通知。
    • 创建步骤:
    • 创建目标对象,目标对象必须是实现了某种接口的。
    • 创建通知,通知定义了一个切面的具体逻辑。
    • 向上下文注册。
  • 72. AOP 快速入门-创建目标
    • public class J2eeCourse implements Course {
    • String name;
    • public J2eeCourse(String name) {
    • this.name = name;
    • }
    • public void process(Teacher teacher) {
    • System.out.println(name + &quot; is in process, and the teacher is “
    • + teacher.getName());
    • teacher.giveClass();
    • }
    • public String getName() {
    • return name;
    • }
    • }
  • 73. AOP 快速入门-创建目标
    • 使用 Java 动态代理机制实现的 AOP 必须要将目标对象中的方法声明在一个接口中:
    • public interface Course {
    • public void process(Teacher teacher);
    • public String getName();
    • }
  • 74. AOP 快速入门-创建通知
    • 此处创建的是前置通知:
    • public class CourseAdvice implements MethodBeforeAdvice {
    • public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
    • Course course = (Course)arg2;
    • Teacher teacher = (Teacher) arg1[0];
    • System.out.println(&quot;hi, teacher &quot; + teacher.getName() +
    • &quot;, there is a &quot; + course.getName()+
    • &quot;, do you have time to listener this class?&quot;);
    • }
    • }
  • 75. AOP 快速入门-注册
    • <beans>
    • <bean id=&quot;courseTarget&quot; class=&quot;aop.J2eeCourse&quot;>
    • <constructor-arg value =” j2ee“/>
    • </bean>
    • <bean id=&quot;rod&quot; class=&quot;aop.TeacherRod&quot;>
    • <constructor-arg value=“Rod Johnson”/>
    • </bean>
    • <bean id=&quot;advice&quot; class=&quot;aop.CourseAdvice&quot;/>
    • <bean id=&quot;course&quot; class=&quot;org.springframework.aop.framework.ProxyFactoryBean&quot;>
    • <property name=&quot;proxyInterfaces&quot; value=“aop.Course”/>
    • <property name=&quot;interceptorNames&quot;>
    • <list><value>advice</value></list>
    • </property>
    • <property name=&quot;target” ref&quot;courseTarget&quot; />
    • </bean>
    • </beans>
  • 76. 通知的类型
    • 通知是切面的具体实现,在 Spring 中通知被分为以下几种类型:
  • 77. 通知的类型
    • 除 MethodInterceptor (环绕通知)是由 aop alliance 定义以外,其余接口均位于 org.springframework.aop 中
    • MethodInterceptor 位于 org.aopalliance.intercept 包中,因此如果需要使用这个接口,必须导入 aopalliance 的 jar 文件。
  • 78. 切入点
    • 切入点用于定义通知加入到目标对象中的位置,没有切入点通知将被应用于所有方法上。
    • Spring 以 org.springframework.aop.PointCut 来定义切入点。
    • 切入点分为两类,即静态切入点和动态切入点
    • 静态切入点下,通知总被执行,动态切入点下,通知依据运行时的参数决定通知是否需要执行。
  • 79. 切入点
  • 80. Advisor 概述
    • 由于 ProxyFactoryBean 只接受 Advice 和 Advisor 类型的 Interceptor (参照 API ),所以不能直接应用 PointCut 到 ProxyFactoryBean 上
    • Advisor 是 Spring AOP 中特有的概念,它持有通知,并决定通知是否应用到当前实例上。
    • 由于切入点是决定通知是否应用的重要依据,故 PointcutAdvisor 中持有通知和切入点,并依据切入点决定是否应用通知。
  • 81. Advisor 概述
    • public interface Advisor {
    • Advice getAdvice ();      
    • boolean isPerInstance ();
    • }
    • public interface PointcutAdvisor extends Advisor {
    • Pointcut getPointcut ()
    • }
    • 由于 PointcutAdvisor 继承自 Advisor ,因此可以当成
    • Interceptor 使用。
  • 82. 内置切入点
    • 静态切入点
    • StaticMethodMatcherPointcut (抽象)
    • NameMatchMethodPointcut -名字匹配
    • JdkRegexpMethodPointcut - JDK 与此同时表达式
    • Perl5RegexpMethodPointcut - Perl 5 正则表达式
    • 动态切入点
    • DynamicMethodMatcherPointcut (抽象)
    • ControlFlowPointcut
  • 83. 名称匹配
    • 在 NameMatchMethodPointcut 中,除了定义了一般 PointCut 的方法外,还定义了以下一些方法:
    • void setMappedName (String mappedName)
    • void setMappedNames (String[] mappedNames)
    • 只有与指定名称匹配的方法才会被应用通知,可以通过 IOC 机制设置匹配名称。
  • 84. 相应 Advisor
    • 与 NameMatchMethodPointcut 对应的 Advisor 是 NameMatchMethodPointcutAdvisor 。
    • 在 NameMatchMethodPointcutAdvisor 中没有定义直接设置 PointCut 的方法,但由于是由 NameMatchMethodPointcutAdvisor 继承而来,故可以通过设置 mappedName 生成。
  • 85. 相应 Advisor
    • <bean id=&quot;advice&quot; class=&quot;aop.CourseAdvice&quot;/>
    • <bean id=&quot;advisor&quot; class=&quot;org.springframework.aop.support.NameMatchMethodPointcutAdvisor&quot;>
    • <property name=“mappedName” value=”process“ />
    • <property name=“advice” ref=&quot;advice&quot; />
    • </bean>
    • <bean id=&quot;course&quot; class=&quot;org.springframework.aop.framework.ProxyFactoryBean&quot;>
    • <property name=&quot;proxyInterfaces“ value=“aop.Course”/>
    • <property name=&quot;interceptorNames&quot;>
    • <list><value> advisor </value></list>
    • </property>
    • <property name=&quot;target“ ref=&quot;courseTarget&quot; />
    • </bean>
    • 在定义 mappedName 时,可以使用通配符 *
  • 86. 正则表达式匹配
    • 通过直接指定方法的办法简单有效,但如果在大型系统中,方法较多的情况下,一个个指出通知的方法名则会显得臃肿。
    • JdkRegexpMethodPointcut 使用正则表达式的形式指定匹配的方法,是更为通用的一种方法。
    • 除了 JdkRegexpMethodPointcut 还有 Perl5RegexpMethodPointcut ,它们的区别仅在于前者使用 JDK 语法,而后者使用 perl 5
  • 87. 正则表达式匹配
    • 无论是 JDK 版本的,还是 Perl5 版本的,它们都是由 AbstractRegexpMethodPointcut 继承而来,这个方法中定义以下两个方法:
    • void setPattern(String pattern)
    • void setPatterns(String[] patterns)
    • 可以使用 IOC 机制定义正则表达式。
    • 特别强调,正则表达式下,匹配的是类名和方法名
  • 88. 相应 Advisor
    • 与这两个 PointCut 对应的 Advisor 都是 RegexpMethodPointcutAdvisor
    • Pointcut getPointcut()
    • void setPattern(String pattern)
    • void setPatterns(String[] patterns)
    • void setPerl5(boolean perl5)
    • 设置 setPerl5 为 true 时,强制使用 Perl 5 语法形式的正则表达式,这时必须引入 Jakarta ORO 包
  • 89. 相应 Advisor
    • <bean id=&quot;advisor&quot; class=&quot;org.springframework.aop.support.RegexpMethodPointcutAdvisor&quot;>
    • <property name=&quot;pattern&quot;>
    • <value .*process.* </value>
    • </property>
    • <property name=&quot;advice&quot;>
    • <ref bean=&quot;advice&quot;/>
    • </property>
    • </bean>
    • 标红处写成 ^aop.Course.process$ 只针对一个类的一个特定方法
  • 90. 数据层应用
  • 91. DAO 支持
    • Spring 提供了对数据层的广泛支持,这包括:
    • 传统 JDBC
    • Hibernate
    • JDO
    • Oracle TopLink
    • Apache OJB
    • iBATIS SQL Map
  • 92. JDBC 方式
    • Spring JDBC 方式采用 模板 与 回调 相结合的模式,核心类是 JdbcTemplate 。
  • 93. JDBC 方式
    • 使用 JDBC 方法处理 DAO ,必须要知道数据源 DataSource 。
    • Spring DAO 层中,获取数据源方法有三种:
    • 通过 JNDI
    • 使用第三方的连接池
    • 使用 DriverManagerDataSource
  • 94. DriverManagerDataSource
    • 为了方便测试, Spring 提供了简便易用的 DataSource 实现,即 DriverManagerDataSource ,可直接创建 :
    • DriverManagerDataSource dataSource = new DriverManagerDataSource();
    • dataSource.setDriverClassName( “……&quot;);
    • dataSource.setUrl( “……&quot;);
    • dataSource.setUsername( “……&quot;);
    • dataSource.setPassword( “……&quot;);
  • 95. DriverManagerDataSource
    • 也可以通过 IOC 机制注入:
    • <bean id=&quot;dataSource&quot; class=&quot;org.springframework.jdbc.datasource.DriverManagerDataSource&quot;>
    • <property name=&quot;driverClassName&quot; value=&quot;com.mysql.jdbc.Driver&quot;/>
    • <property name=&quot;url&quot; value=&quot;jdbc:mysql://localhost:3306/hibernate&quot;/>
    • <property name=&quot;username&quot; value=&quot;root&quot;/>
    • <property name=&quot;password&quot; value=&quot;root&quot;/>
    • </bean>
  • 96. 第三方连接池
    • 最常使用的第三方连接池是 Apache 的 jakarta common dbcp 项目。这里主要使用的是 org.apache.commons.dbcp.BasicDataSource
    • 由于 BasicDataSource 的属性均通过 setter 方法暴露出来,因此可以使用 IOC 机制注入。
    • 例如:
  • 97. 第三方连接池
    • <bean id=&quot;newDs&quot; class=&quot;org.apache.commons.dbcp.BasicDataSource&quot;>
    • <property name=&quot;driverClassName&quot; value=&quot;com.mysql.jdbc.Driver&quot; />
    • <property name=&quot;url&quot; value=&quot;jdbc:mysql://localhost:3306/hibernate&quot; />
    • <property name=&quot;username&quot; value=&quot;root&quot; />
    • <property name=&quot;password&quot; value=&quot;root&quot; />
    • </bean>
  • 98. JNDI 方式
    • <bean id=&quot;dataSource&quot; class=&quot;org.springframework.jndi.JndiObjectFactoryBean&quot;>
    • <property name=&quot;jndiName&quot; value=&quot;java:comp/env/jdbc/DataSource&quot;/>
    • </bean>
    • <bean id=&quot;jt&quot; class=&quot;org.springframework.jdbc.core.JdbcTemplate&quot;>
    • <property name=&quot;dataSource&quot; ref=&quot;dataSource&quot;/>
    • </bean>
    • 注意, JdbcTemplate 中的 dataSource 是 DataSource 类型,但设置的却是 JndiObjectFactoryBean 。
  • 99. JdbcTemplate
    • 总的来说, Spring 在支持 JDBC 访问数据库时采用了模板与回调相结合的方式。其中:
    • JdbcTemplate 是模板;
    • StatementCallback 是执行 Statement 语句的回调;
    • PreparedStatementCallback 、 PreparedStatementCreator 、 PreparedStatementSetter 是 PreparedStatement 语句的回调
    • CallableStatementCallback 等是 CallableStatement 语句的回调。
  • 100. JdbcTemplate 查询
    • 依据模板回调原则, Spring 定义了以下查询方法:
    • Object query(PreparedStatementCreator psc, ResultSetExtractor rse)
    • List query(PreparedStatementCreator psc, RowCallbackHandler rch)
    • List query(PreparedStatementCreator psc, RowMapper rowMapper)
    • 以上几个方法中,第一个参数用于生成语句,第二个参数则用于处理结果,它们都用于在运行时回调
  • 101. JdbcTemplate 查询
    • Spring 提供了一些简便的查询方法:
    • 1. temp. queryForList (&quot;select * from building&quot;);
    • 返回 List ,内部元素为 Map ,键对象为列名,值对象为列值。
    • 2. temp. queryForMap (&quot;select * from building where id=3&quot;);
    • 返回 Map ,键对象为列名,值对象为列值,所以要求必须返回单一行。
    • 3. temp. queryForObject (&quot;select building_name from building where id=1&quot;, String.class)
    • 返回对象,依据指定的类型决定返回对象的类型,仅针对单行单列
    • 4. 此外还有 queryForInt 及 queryForLong 等等。
  • 102. JdbcTemplate 更新
    • 依据模板回调原则, Spring 定义了以下更新方法:
    • int update(PreparedStatementCreator psc)
    • int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder)
    • int update(PreparedStatementCreator psc, PreparedStatementSetter pss)
    • 以上参数也均为方法提供了运行回调接口。
  • 103. JdbcTemplate 更新
    • 为了方便, Spring 同样定义更新使用的方法:
    • int update(String sql)
    • int update(String sql, Object[] args)
    • int update(String sql, Object[] args, int[] argTypes)
    • int update(String sql, PreparedStatementSetter pss)
    • 用法参照 API
  • 104. 映射对象
    • Spring 同 Hibernate 类似,也可以将查询结果映射成对象,但这需要用户自定义。
    • 这是通过 SqlQuery 和 SqlUpdate 类实现的,前者用于查询,后者用于更新。 SqlQuery 是抽象类,一般使用其子类 MappingSqlQuery 类派生子类。
  • 105. 映射对象
  • 106. 映射对象
  • 107. 整合 Hibernate
    • Hibernate 的核心是 SessionFactory ,它就像 JDBC 中的 DataSource 一样。
    • Spring 提供了以 IOC 机制导入 SessionFactory 的可能,这是通过 LocalSessionFactoryBean 实现的。
    • 由于 Hibernate 版本更新向前不兼容,因此 Spring 也提供了两套接口对于不同的 Hibernate 版本。
    • org.springframework.orm.hibernate 支持 Hibernate 2.1 ,而 org.springframework.orm.hibernate3 则支持 hibernate3
  • 108. 整合 Hibernate
  • 109. 整合 Hibernate
    • 在应用上, Spring 也提供了模板与回调模式来实现 Hibernate 对数据库的操作。
    • HibernateTemplate 是模板,而 HibernateCallback 则是回调接口。
    • HibernateTemplate 提供的 execute 方法,需要以 HibernateCallback 为参数,执行时则在合适的时候回调对象。
  • 110. 整合 Hibernate
    • 类似于 JdbcTemplate , HiberateTemplate 中也加入了一些简便的方法,可以实现增、删改操作。
    • 这些方法基本都可以在 Hibernate 的 Session 接口中找到,或者是 HQL 、 QBC 、 QBE 等等。
    • 具体参照 API 文档
  • 111. 表述层应用
  • 112. 集成 Struts
    • Spring 提供了三种集成 Struts 的方法:
    • 显式集成
    • Action 代理
    • RequestProcessor 代理
    • 无论是哪种方法都必须先向 Struts 框架注册一个插件,即:
  • 113. 显式集成
    • 显示集成 Struts 时要求所有需要使用 Spring 的 Action 都必须通过显式继承 ActionSupport ,位于 org.springframework.web.struts. 包中
    • 这个类是 Action 的子类,包含了能够得到 ApplicationContext 的方法,即
    • WebApplicationContext getWebApplicationContext()
  • 114. Action 代理
    • Action 代理方式集成 Struts 需要将所有 Action 的地址都映射到 DelegatingActionProxy 上,位于 org.springframework.web.struts 包中。
    • 它也是 Action 的子类,代理所有 Action 请求。真正的 Action 请求则以 Spring 注册 bean 的形式注册在容器中,如:
  • 115. Action 代理 多模块时,路径如何写?
  • 116. RequestProcessor 代理
    • RequestProcessor 代理的方式是改写了模块控制器,要求模块控制器必须是 DelegatingRequestProcessor 。
    • 这时,所有的 Action 都会被转到 Spring 中查找,所以在 Struts 中配置 action 的 type 属性已经没有意义:
  • 117. Spring 事务支持
    • Spring 最为自豪的当属事务管理,因为它在不使用 EJB 服务器的情况下,实现了对事务的宣称式支持。这在以往是仅能由 Session Bean 提供的功能。
    • Spring 对事务的宣称式支持是通过 AOP 机制实现,也即在需要声明事务属性的方法中织入通知。
  • 118. Spring 事务支持
  • 119. Spring 事务支持 注:以上类均实现了 PlatformTransactionManager
  • 120. Spring 事务支持
    • 由于不同的平台实现事务管理采用的是不同的资源,例如 JDBC 使用直接使用 Connection 管理事务,而 Hibernate 则使用 Session 。
    • 在实现上, Spring 要求为 JDBC 事务管理器注入数据源 DataSource ,而为 Hibernate 事务管理器注入 SessionFactory
    • 所以使用不同的数据层解决方案,相应的事务管理器也完全不同。
  • 121. Spring 事务支持
  • 122. Spring 事务支持
    • 与 EJB 相同, Spring 对事务的支持也分为编程式和宣称式两种(对应 EJB 的 BMT 和 CMT )。
    • 在 编程式 事务管理中, Spring 依然采用了模板与回调模式。
    • 在 宣称式 事务管理中, Spring 采用了与 EJB 类似的 事务属性 来管理事务。
  • 123. 编程式事务管理
    • Spring 提供了两种方式实现编程式事务管理:
    • 1 、使用 TransactionTemplate 与 TransactionCallback 结合。
    • 2 、直接使用一个 PlatformTransactionManager 的实现。
  • 124. 编程式事务管理
    • 使用 TransactionTemplate 时,在其内部仍然要知道具体的事务管理平台,即 PlatformTransactionManager 。这可以通过 IOC 机制注入。如
  • 125. 编程式事务管理
  • 126. 编程式事务管理
    • 事实上, Spring 为模板提供了两个回调类,即 TransactionCallbackWithoutResult 和 TransactionCallback ,前者是后者的实现,并且是一个抽象类。
    • TransactionStatus 作为参数传给回调函数,通过 TransactionStatus 可以设置事务只可回滚。
    • 需要注意, 运行时异常可导致自动回滚 。其余则必须设置成只可回滚。
  • 127. 编程式事务管理
    • 也可直接使用 PlatformTransactionManager :
  • 128. 宣称式事务
    • Spring 宣称式事务与 Session Bean 的 CMT 事务管理在使用上极为相似,但是在很多方面 Spring 要优于 EJB :
    • EJB 事务管理是绑定在 JTA 上的,而 Spring 则可以应用在任何情况下。
    • EJB 事务管理不支持 POJOs
    • Spring 提供声明式回滚规则,并且可以通过 AOP 在事务中定制其它行为
    • Spring 不依赖服务器
    • 但有一点, Spring 是无法取代 EJB 的,那就是分布式的事务管理。
  • 129. 宣称式事务
    • Spring 的宣称式事务管理实际上是应用了 Spring 的 AOP 特性,将事务管理的代码织入到原代码中。
    • 使用的代理类是 TransactionProxyFactoryBean ,位于 org.springframework.transaction.interceptor 包
  • 130. 宣称式事务
  • 131. 传播行为
  • 132. 传播行为