• 1. Spring(1. IOC)
  • 2. AgendaSpring框架简单介绍 相关术语 Spring的主要功能 IOC
  • 3. Spring框架简单介绍 Spring的核心是个轻量级(Lightweight)的容器(Container),它是实现IOC(Inversion of Control)容器和非侵入性(No intrusive)的框架,并提供AOP(Aspect-oriented programming)概念的实现方式;提供对持久层(Persistence)、事务(Transaction)的支持;提供对MVC Web框架的实现,并对于一些常用 的企业服务API(Application Interface)提供 一致的模型封装,是一个全方位的应用程序框架(Application framwork),除此之外,对于现存的各种框架(Struts, JSF, Hibernate等),Spring也提供了与它们相整合的方案。
  • 4. Spring是一个轻量级的j2ee的框架,核心是功能强大的容器IoC,在容器的基础上又提供对AOP的支持,以及对持久层和表示层的数据封装,同时也对持久层和表示层组件的支持. 区别Struts和Hibernate: Struts是实现MVC模式的WEB组件,是一个比较成熟的被广泛应用在WEB应用系统的View层。 Hibernate是成熟的ORM组件,主要应用实现数据持久层的功能,而最大的作用是面向对象的 java语言与关系数据库之间的桥梁,是我们的开发人员可以直接通过对java对象的持久化操作来完成对数据持久化的操作。Spring框架简单介绍
  • 5. 相关术语轻量级(Lightweight) 轻量级是相对于一些重量级的容器(如EJB容器)来说的,Spring的核心包在文件容量上只有不到1MB的大小,使用Spring核心包所需要的资源也是很少的,您甚至可以在小型设备中使用Spring。 (现在轻量级和重量级的确很难区分了,标准越来越多,也越来越难以衡量。EJB有轻量化的倾向,Spring也有重量化的趋势。Spring core算是轻量级,但是加上其余的部件,估计也得列入重量级的范畴了。) 非侵入性(No intrusive) 框架原来的用意是提供一个架构的实现,让开发人员可以在基本框架的基础上,快速地开发出遵循架构所需的应用程序,然而有些框架一量被使用,应用程序就对框架有了依赖性,例如使用了大量框架的API,或者直接继承API的某些类型等。
  • 6. 相关术语Inversion of Control与Dependency Injection “控制反转” -IOC。 “依赖注入” -DI AOP(Aspect-oriented programming) 例如:应用程序有个日志的需求,您可以无须修改任何一行程序代码,就将这个需求加入到原先的应用程序中,而若您愿意,也可以在不修改任何程序的情况下,将这个日志功能移除。
  • 7. 控制反转(IoC) 依赖注入(Dependency Injection) 服务定位(Service Locator) 面向切/方面的编程(AOP) 持久层的封装和事务管理 提供了对Web的多种支持Spring主要功能
  • 8. 1、对于设计良好的软件系统,对象之间的依赖关系应该满足什么样的特征? <1> 模块之间不进行直接相互调用 对于不同模块之间不应该进行直接调用。也就是说,不同模块之间的依赖关系要通过抽象类(或者接口)来实现,而不是直接调用对方的具体实现。这样做的好处是,一个模块实现方法的改变不会影响另一个模块。 <2> 抽象类不能依赖于实现类 抽象类不能依赖于具体实现,而反过来,具体实现类则必须依赖于抽象类。 <3> 应用不应该依赖于容器 在应用程序中使用的各种容器都是为应用程序所服务的 ,因此不能对其产生依赖性。否则,将会大大降低应用程序的可移植性。 控制反转(IOC)
  • 9. 控制反转(IOC) 应用程序 储存的需求 saveToFloppy()… void saveToFloppy(){ … } }直接在高层的应用程序中调用低层模块的API,导致应用程序对低层模块产生依赖…
  • 10. IOC的control是控制的意思,其实背后的意义也是一种依赖关系的转移。如果A依赖于B,其意义其B拥有控制权。如果转移这种关系(依赖关系的反转即控制关系的反转),将控制权由实现的一方转移至抽象的一方,由抽象方拥有控制权,可以获得组件的可重用性。控制反转(IOC)
  • 11. 2、IoC容器: <1> 没有IoC容器就没有Spring框架 IoC容器是spring框架的基础,是spring框架中实现其他功能的基础 Spring的IoC容器最大特点是实现了反转控制,也就是说在开发的过程中,开发人员不需要关心容器是怎么样的,也不需要调用容器的任何API。容器会自动进行被管理对象的初始化以及对象之间依赖关系的维护。 <2> 自动地依据对象之间的依赖关系来创建对象,对象的创建方法、参数以及对象之间的依赖关系由配置文件来描述; 解决了抽象类不依赖于具体实现类的目的; <3> 应用程序在开发中不应该调用任何容器所提供的API,应用不应该依赖于容器。 控制反转(IOC)
  • 12. <3> IoC容器工作原理示意图 The spring containerFull configured system Ready for useMagic happens hereYour Business Objects (POJOS)Configuration Metadataproduces控制反转(IOC)
  • 13. <4> 配置原数据 如何配置Bean以及Bean 之间的关系,如何进行Bean的实例化及Bean的实例对象之间关系的管理。 有三种方式: 用xml格式(通用的配置方式) 属性文件 通过Spring所提供的API来通过编程的方式进行Bean的初始化工作 控制反转(IOC)
  • 14. 15. <5> 容器的初始化 在初始化时,需要一个用于访问配置文件的org.spring.framework.core.io.Resource对象的参数来做为构建容器的对象的参数;Resource是一个接口,提供一个使用不同方式访问资源文件的统一方法; Resource resource=new FileSystemResource(“/user/local/beans.xml”); BeanFactory factory=new XmlBeanFactory(resource); 在实际应用中,用的更多的,是通过类路径的方式访问配置文件也就是spring提供了这样一个类ClassPathResource 来访问配置文件。 ClassPathResource resource = new ClassPathResource("com/xml/beans.xml"); BeanFactory factory = new XmlBeanFactory(resource); 控制反转(IOC)
  • 16. <6> IoC 容器的使用 一个简单的例子,来了解IoC容器的基本用法: 开发业务处理对象: public class IoCService { private String message;//基本属性 public String getMessage() { return message; } //提供set方法,为了在IOC容器中进行初始化 public void setMessage(String message) { this.message = message; } public void display( ) {//基本的业务方法 System.out.println( getMessage() ); } } 控制反转(IOC)
  • 17. 控制反转(IOC)配置Bean: Hello! IoC container!
  • 18. //测试主程序的实现 package cn.spring.ioc; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.ClassPathResource; public class IoCMain(){ public static void main(String args[ ]){ ClassPathResource resource=new ClassPathResource(“cn/spring/ioc/IoCBeans.xml”); BeanFactory factory=new XmlBeanFactory(resource); IoCService service= (IoCService)factory.getBean(“iocService”); service.display(); } } 执行结果是输出字符串: “Hello! IoC container!”控制反转(IOC)
  • 19. 配置文件的合并 Spring的IoC容器除了可以管理业务对象外,还可以管理访问数据库时使用的DAO,表示层使用的Action等由于任何Java对象都可以通过Spring的IoC容器来进行管理,所以其配置文件就会变得非常复杂和庞大。因此,在实际的项目中,会按照被配置对象的特征或项目的功能模块来将配置信息放置在不同的配置文件中。 Spring提供了两种解决方案, 一种是通过编程的方式来逐一加载配置文件, 另一种是使用元素从另一个或多个文件加载Bean定义,合并方法如下所示:
  • 20. 配置文件的合并配置文件的合并方法: . .
  • 21. BeanFactoryBeanFactory负责读取Bean定义文件;管理对象的加载、生成;维护Bean对象与Bean对象之间的依赖关系;负责Bean的生命周期。 API: boolean containsBean(String) //测试BeanFactory中是否包含指定名称的Bean Object getBean(String) //指定Bean定义文件中设置的名称,可取得相对应的Bean实例 Object getBean(String, Class) //..(同上),并转换(Cast)至指定的类 boolean isSingleton(String)//…. String[] getAliases(String) //指定Bean定义文件中设置的名称,取得该Bean所有的别名
  • 22. ApplicationContext 作为一个应用程序框架,只提供Bean容器管理的功能是不够的,若要用Spring所提供的一些特色以及高级的容器功能,可以使用org.spring.framework.context.ApplicationContext。ApplicationContext是基于BeanFactory而建立的,也具备读取Bean定义文件,维护Bean之间的依赖关系等功能,除此之外,ApplicaitonContext还提供一个应用程序所需的更完整的框架功能,如:
  • 23. ApplicationContext提供更方便地取得资源文件(Resource file)的方法。 提供解析文字消息的方法。 支持国际化(Internationlization, I18N)消息 ApplicationContext可以发布事件,对事件感兴趣的Bean可以接收到这些事件。
  • 24. Bean的识别名称与别名 在定义文件中使用标签时可以使用“id”指定Bean的识别名称,当您需要多个Bean定义文件时,最好规范“id”名称的命名方式,以免名称上的冲突。在设置了“id”属性之后,您还可以为Bean设置别名,例如考虑在A定义文件中要参考一个“device:dataSource”的Bean实例,而在B定义文件中要参考一个“user:dataSource”的Bean实例,但实际上DataSource的实例在应用程序中只存在一个,这就可以采用别名的方式为该实例指定别名。如:
  • 25. Bean的识别名称与别名 在其它定义文件中,可以直接参考别名
  • 26. Bean的创建Spring的IoC容器具有Bean对象实例化的功能,对常用的对象实例化方法和设计模式提供了支持。主要包括以下三种: 使用构造方法创建Bean实例 使用静态工厂方法创建Bean的实例。 使用实例化的工厂方法创建Bean的实例。 使用构造方法创建Bean实例,配置方法如下: 等价于 new constructBean()来实现对象的实例化
  • 27. 使用静态工厂方法创建bean的实例,配置方法如下: 等价于 IoCServiceFactory1. getIoCServiceInstance() Bean的创建
  • 28. Bean的创建使用实例化工厂方法创建bean的实例,配置方法如下: 等价于: IoCServiceFactory2 iocServiceFactory = new IoCServiceFactory2 (); iocServiceFactory. getIoCServiceInstance();
  • 29. 主程序测试: public class IoCMain { public static void main(String[] args) { ClassPathResource resource = new ClassPathResource("com/ioc/xml/IoCBeans.xml"); BeanFactory factory = new XmlBeanFactory(resource); IoCService service = (IoCService)factory.getBean( "iocService" ); IoCService service1 = (IoCService)factory.getBean( "iocService" ); IoCService service2= (IoCService)factory.getBean( "iocService" ); service.display(); service1.display(); service2.display(); } }Bean的创建
  • 30. Bean的Scope在Bean的配置文件中,不仅可以控制Bean的各种依赖关系,还可以控制该对象的作用域,作用域的配置是通过元素的scope属性来进行配置的。 Spring框架默认支持5种作用域: singleton IoC容器只会创建该Bean的唯一实例; prototype IoC容器在每次请求该Bean的时候都会创建一个新的实例;
  • 31. Bean的Scoperequest 在一次HTTP请求中,IoC容器会返回该Bean的同一个实例,对于不同的用户请求,则会返回不同的实例; session 在一个HTTP session 中,IoC容器会返回该Bean的同一个实例,对于不同的用户session,则会返回不同的实例; global session 在一个全局的HTTP session中,IoC容器会返回该Bean的同一个实例。
  • 32. Bean的scopeNote: Bean的作用域中request,session和global session只能在Web应用环境中使用ApplicationContext的时候使用。 对于使用singleton作用域的Bean,通常都是无状态的。 同一个 Java对象可以使用元素进行多次定义,IoC容器会独立地处理每一个元素所进行的定义。
  • 33. 依赖注入是Spring IoC容器实现反转控制的方式, Spring 的IoC容器以依赖注入的方式实现了Bean对象之间关系的维护。 两种方式的对象注入: 1、基于构造方法的依赖注入 先看一个简单的例子: <1>实现Bean对象 package com.injection.bean; public class ConstructInjectionBean { private AnotherBean anotherBean; private YetAnotherBean yetAnotherBean; private int i; Construct Injection
  • 34. public ConstructInjectionBean( AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) { this.anotherBean = anotherBean; this.yetAnotherBean = yetAnotherBean; this.i = i; } public void display() { System.out.println( "ConstructInjectionBean:" ); System.out.println( this.anotherBean ); System.out.println( this.yetAnotherBean ); System.out.println( i ); } }Construct Injection
  • 35. Construct Injection <2>配置Bean
  • 36. Construct Injection
  • 37. 测试主程序 public class InjectionMain { public static void main(String[] args) { ClassPathResource resource = new ClassPathResource("com/injection/xml/InjectionBeans.xml"); BeanFactory factory = new XmlBeanFactory(resource); /** * 构造方法依赖注入 */ ConstructInjectionBean constructInjectionBean = (ConstructInjectionBean)factory.getBean( "constructInjectionBean" ); constructInjectionBean.display(); } }Construct Injection
  • 38. 上面的配置类似于下面的java代码: AnotherBean anotherBean=new AnotherBean(); YetAnotherBean yetAnotherBean=new YetAnotherBean(); ConstructInjectionBean constructInjectionBean=new ConstructInjectionBean (anotherBean, yetAnotherBean,1); 注: 在使用构造方法进行Bean的初始化时,Bean类中构造参数与XML配置文件中的配置元素应该是一一对应的;Construct Injection
  • 39. Setter Injection2、基于setter方法的依赖注入 使用setter方法的依赖注入,需要首先通过调用无参构造器或无参静态工厂方法实例化Bean,然后再调用该Bean的setter方法实现setter依赖注入; 一个简单的例子:
  • 40. Setter Injectionpublic class SetterInjectionBean { private AnotherBean anotherBean; private YetAnotherBean yetAnotherBean; private int i; public AnotherBean getAnotherBean() { return anotherBean; } public void setAnotherBean( AnotherBean anotherBean) { this.anotherBean = anotherBean; } public int getI() { return i; } public void setI(int i) { this.i = i; } public YetAnotherBean getYetAnotherBean() { return yetAnotherBean; } public void setYetAnotherBean( YetAnotherBean yetAnotherBean) { this.yetAnotherBean = yetAnotherBean; } public void display() { System.out.println( "SetterInjectionBean:" ); System.out.println( this.anotherBean ); System.out.println( this.yetAnotherBean ); System.out.println( i ); } }
  • 41. Setter Injection
  • 42. //测试主程序 public class InjectionMain { public static void main(String[] args) { ClassPathResource resource = new ClassPathResource("com/injection/xml/InjectionBeans.xml"); BeanFactory factory = new XmlBeanFactory(resource); /** * 基于setter方法的依赖注入 */ SetterInjectionBean setterInjectionBean = (SetterInjectionBean)factory.getBean( "setterInjectionBean" ); setterInjectionBean.display(); } } Setter Injection
  • 43. 自动绑定 除了在Bean定义文件中使用指定字符串以及基本类型值,使用直接指定参考至其它Bean实例,或是使用标签指定“class”属性,用来指定依赖对象外,Spring也支持隐式的自动绑定。 可以使用: byName byType autodetect
  • 44. HelloBean.javaimport java.util.Date; public class HelloBean { private String helloWord; private Date date; public void setHelloWord(String helloWord) { this.helloWord = helloWord; } public String getHelloWord() { return helloWord; } public void setDate(Date date) { this.date = date; } public Date getDate() { return date; } }
  • 45. beans-config.xml
  • 46. 集合对象Injection配置方式如下: Hello Welcome ListTest Hello!Justin!
  • 47. Lookup方法注入的作用: 问题: 假设A为singleton类型的Bean, B为prototype类型的Bean, A需要引用B由于A只会被创建并初始化一次,这样就没办法让每次得到的A对象的实例都包含一个新的B对象的实例。 解决办法: Spring IoC容器提供了Lookup方法注入的方式来解决上述类似问题; example: Lookup方法注入
  • 48. Lookup方法注入在使用Lookup方法注入时,需要在引用的Bean中定义一个返回被引用对象的抽象方法 Lookup方法注入利用了Spring IoC容器复写Bean的抽象(或具体)方法的能力,从而返回指定名字的Bean实例。 Lookup方法注入的内部机制是Spring利用CGLIB库在运行时生成二进制代码,通过动态创建Lookup方法Bean的子类而达到复写Lookup方法的目的。 在进行XML配置的时候,使用来指定所要覆盖的方法和返回的 Bean.
  • 49. Message.javaimport java.util.Date; public class Message { private String sysMessage; public Message() { sysMessage = "系统消息: " + new Date().toString(); } public String toString() { return sysMessage; } }
  • 50. MessageManager.javapublic abstract class MessageManager { public void display() { Message message = createMessage(); System.out.println(message); } protected abstract Message createMessage(); }
  • 51. SpringDemo.javaimport org.springframework.context.ApplicationContext; import org.springframework.context.support. ClassPathXmlApplicationContext; public class SpringDemo { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "beans-config.xml"); MessageManager messageManager = (MessageManager) context.getBean("messageManager");
  • 52. SpringDemo.javatry { messageManager.display(); Thread.sleep(1000); messageManager.display(); Thread.sleep(1000); messageManager.display(); } catch (InterruptedException e) { e.printStackTrace(); } } }
  • 53. beans-config.xml
  • 54. CustomEditorConfigurer Spring框架提供了一个BeanFactoryPostProcessor接口的实现类:org.springFramework.beans.factory.config.CustomEditorConfigurer 这个类可以读取实现java.beans.PropertyEditor接口的类,并按其中的实现,将字符串值转换为指定类型的对象。
  • 55. UserEditor.javaimport java.beans.PropertyEditorSupport; public class UserEditor extends PropertyEditorSupport { public void setAsText(String text) { String[] strs = text.split(","); int number = Integer.parseInt(strs[1]); User user = new User(); user.setName(strs[0]); user.setNumber(number); setValue(user); } }
  • 56. HelloBean.javapublic class HelloBean { private String helloWord; private User user; public void setHelloWord(String helloWord) { this.helloWord = helloWord; } public String getHelloWord() { return helloWord; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
  • 57. beans-config.xml
  • 58. beans-config.xml
  • 59. SpringDemo.javaimport org.springframework.context.ApplicationContext; import org.springframework.context. support.ClassPathXmlApplicationContext; public class SpringDemo { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "beans-config.xml"); HelloBean hello = (HelloBean) context.getBean("helloBean"); System.out.println(hello.getHelloWord() + "!"); System.out.println("Name:\t" + hello.getUser().getName()); System.out.println("Number:\t" + hello.getUser().getNumber()); } }
  • 60. Bean的其他特性定义初始化方法和销毁方法 初始化方法是在对象创建之后并且完成了配置文件中所配置的setter注入工作完成之后执行,在IoC的配置中,可以通过元素的元素来指定被调用的初始化方法。 销毁方法在对象被容器销毁的时候执行,可以用来进行一些资源的释放工作,在IoC的配置中,可以通过元素的元素来进行销毁方法的指定。 depends-on的使用 depends-on属性可以用于当前Bean初始化之前显示地强制一个或多个Bean被初始化。若需要表达对多个Bean的依赖,可以在中将多个Bean名字用分隔符进行分割,分隔符可以是逗号,空格及分号。
  • 61. Bean的其他特性延迟初始化Bean ApplicationContext实现的默认行为是在启动时将所有Singleton Bean提前进行实例化,如果不想让一个singleton Bean在ApplicationContext实现初始化时被提前实例化,那么可以将Bean设置为延迟实例化,通过元素的lazy-init属性来进行控制。 注意:如果一个延迟初始化的Bean被一个非延迟话的Bean所依赖,那么该延迟初始化Bean也会在初始化阶段就被初始化的。
  • 62. ENDThanks!Q & A