Spring是一个从实际开发中抽取出来的框架,因此它完成了大量开发中通用步骤,留给开发者的仅仅是与特定应用相关的部分,从而大大提高企业应用的开发效率。
Spring提供的是一个轻量级的解决方案,包括:基于依赖注入的核心机制,基于 AOP 的声明式事务管理,与多种持久层技术的整合,以及优秀的 MVC 框架等。
Spring的优点:低侵入式设计,代码的污染比较低;独立于各种应用服务器; Spring 的 DI 机制降低了业务对象替换的复杂性; Spring 的高度开放性,开发者自由选用 Spring 框架的部分或全部。
*********************************************************************
Spring的下载:
http://www.springframework.org
解压缩的文件夹,有如下几个文件夹:
Aspectj :包含 Spring 支持 Aspectj 所需类的源代码
dist : Spring 的架包,通常只需要 spring.jar 文件即可
docs : Spring 的相关文档、开发指南和 API 参考文档
lib : Spring 编译和运行所依赖的第三方类库
mock : Spring 测试框架中的几个 mock 类,以及对应的测试用例
samples : Spring 的几个简单示例
src : Spring 的全部源码
test : Spring 的测试用例,可以作为学习 Spring 的入门代码
tiger :存放 JDK1.5 的相关内容
*********************************************************************Web中应用中使用Spring ( Eclipse 中开发 Spring 应用)
1、 启动Eclipse 工具,新建一个 Spring 项目,命名为 myspring
2、 单击Next 按钮,接着单击 finish 按钮,建立项目成功
3、 项目建立成功,在Eclipse 的左边见到项目的结构树
4、 右击myspring ,单击 Build Path 菜单项,单击 Add Libraries
5、 选中User Library 项,单击 Next ,选择并添加用户库的对话框
6、 单击finish ,为项目编译和运行增加用户库成功
7、 为项目添加logoj.properties 文件,用来控制日志输出, myspring/src 路径下
# rootLogger是所有日志的跟日志,修改该日志属性对所有日志起作用
# 下面的属性配置中,所有日志的输出级别是 DEBUG ,标准输出源 stdout
log4j.rootLogger=DEBU, stdout
# 定义输出源 stdout 的输出位置的是控制台
log4I.appender.stdout=org.apache.log4j.ConsoleAppender
# 定义输出日志布局采用的类
log4I.appender.stdout.layout=org.apache.log4j.PatternLayout
# 定义输日志的布局
log4I.appender.stdout.layout.ConversionPattern=%c{1} - %m%n
8、 编写Spring 配置文件, Spring 通过配置文件管理 Java 组件, myspring/src 路径下
9、 编写主程序:初始化Spring 容器( Spring 的核心),负责管理 Java 组件
ApplicationContext ctx = new ApplicationContext("beans.xml");
10、 为了让Spring 管理容器中的 Bean ,增加一个 Java 类文件( Person 类)
11、 将Person 类配置到 Spring 的配置文件中
<bean id="person" class="vivi.test.spring.Person">
<property name="name" va;ue="vivi">
</bean>
12、 修改主程序,添加代码:
Person p = (Person)ctx.getBean("person");
Spring容器根据配置文件信息,负责创建 Person 实例,并为 Person 实例设置属性值
*********************************************************************
Spring的核心机制 --- 依赖注入
依赖注入不仅可以注入普通的属性值,还可以注入其他Bean 的引用,通过依赖注入各种组件不需要以硬编码的方式耦合在一起,甚至无须使用工厂模式。
依赖注入让Spring 的 Bean 以配置文件组织在一起,而不是硬编码的方式耦合在一起。
控制反转(Inversion of Control ) == 依赖注入( Dependency Injection ):当调用者需要一个被调用者,创建被调用者的工作不再由调用者来完成,因此成为 控制反转 ,创建被调用者实例的工作由Spring 容器来完成,然后注入调用者,因此也称为 依赖注入 。
比喻:
1、 原始社会需要斧头,自己生产(new ),程序高度耦合,效率低下
2、 工业社会需要斧头,定位工厂、购买斧头;无须知道斧头的生产过程,面向接口编程,调用者与被调用者,实现很好的解耦
3、 程序无须理会被调用者的实现,也无须定位工厂,实例之间的依赖关系由容器提供
*********************************************************************
面向接口编程,可以更好地让规范和实现分离,从而提供更好的解耦
依赖注入:
1、设值注入
※ 通过setter 方法传入被调用者的实例,简单、直观。
<!--定义第一个 Bean ,该 Bean 的 id 是 chinese , class 指定该 Bean 实现类 -->
<bean id="chinese" class="vivi.Chinese">
<!--property元素指定容器注入的属性 -->
<property name="axe" ref="stoneAxe" />
</bean>
<bean id="stoneAxe" class="vivi.StoneAxe" />
※ property定义的属性值不再由该 Bean 来主动创建和管理,而是接受 Spring 的注入。
※ 每个Bean 的 id 属性是该 Bean 的唯一标识,通过 id 属性访问 Bean , Bean 与 Bean之间的依赖关系也通过 id 属性关联
※ 不仅创建了Person 的默认实例,还为该实例依赖注入可 Person 实例依赖的 Axe 实例
2、 构造注入
※ 在构造实例时,已经完成了属性的初始化,利用构造函数来设置依赖关系
<bean id="chinese" class="vivi.Chinese">
<!--constructor-arg元素:使用构造注入 -->
<constructor-arg ref="stoneAxe" />
</bean>
<bean id="stoneAxe" class="vivi.StoneAxe" />
3、 两种方式的对比
※ 设置注入,程序开发人员更容易接受和了解、对于复杂的依赖关系,构造注入,难以阅读、性能下降
※ 构造器中决定依赖关系的注入顺序、依赖关系无须变化的Bean 使用构造注入,更稳定、符合高内聚的原则,依赖关系只在构造器中设定
*********************************************************************
Spring容器:
用于管理容器中的Bean , BeanSpring 管理的基本单位,在 Spring 的 J2EE 应用中,所有的组件都是 Bean 。 Spring 容器必须精确配置 Bean 的实现类。
1、 BeanFactory容器
负责配置、创建、管理Bean 、 Bean 和 Bean 之间的依赖关系
※ public boolean containsBean(String name):是否包含 id 为 name 的 Bean
※ public Object getBean(String name):返回 id 为 name 的 Bean
※ public Object getBean(String name, Class requiredType):返回 id 为 name 的Bean ,并且类型为 requiredType 的 Bean
※ public Class getType(String name):返回 id 为 name 的 Bean 的类型
创建BeanFactory 时,必须提供 Spring 容器管理的 Bean 的详细配置信息, Spring 通常以 XML配置文件设置。 XML 配置文件通常使用 Resource 对象传入。
//搜索当前路径下的 beans.xml 文件创建 Resource 对象
InputStream is = new FileInputStream("bean.xml");
InputStreamResource isr = new FileSystemResource(is);
XmlBeanFactory factory = new XmlBeanFactory(isr);
--------------------------------------------------------------------------------
//搜索 CLASSPATH 路径下的 beans.xml 文件创建 Resource 对象
ClassPathResource res = new ClassPathResource("beans.xml");
XmlBeanFactory factory = new XmlBeanFactory(res );
2、 ApplicationContext容器时 BeanFactory 容器的子接口
如果有多个配置文件,则应该采用ApplicationContext 来创建 BeanFactory 的实例
//CLASSPATH路径下的配置文件
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext (new String[] {"applicationContext.xml" , "service.xml"});
BeanFactory factory = (BeanFactory) appContext ;
--------------------------------------------------------------------------------
//指定路径下的配置文件
FileSystemXmlApplicationContext appContext = new FileSystemXmlApplicationContext (new String[] {"applicationContext.xml" , "service.xml"});
BeanFactory factory = (BeanFactory) appContext ;
ApplicationContext容器,有时候也称 Spring 容器为 Spring 上下文
支持以声明式操作容器,无须手动创建
可利用如ContextLoader 的支持类,在 Web 应用启动时自动创建 ApplicationContext
*********************************************************************
国际化
ApplicationContext继承 MessageSource 接口,支持国际化
3个用于国际化的方法:
1、 String getMessage(String code, Object[] args, Locale loc)
2、 String getMessage(String code, Object[] args, String default,Locale loc)
3、 String getMessage(MessageSourceResolvale resolvable, Locale loc)
ApplicationContext加载时,自动查找配置文件中的 MessageSource ,该国际化资源 Bean 的名字必须是 messageSource ,找到这个 Bean ,上述三个方法的调用被委托给 messageSource Bean 。如果没有找到 messageSource Bean ,将实例化空的 StaticMessageSource Bean ,接受上述三个方法的调用。
<bean id="messageBean" class="org.springframework.context.support.ResourceBundleMessageSource"
<property name="basenames">
<list>
<value>message</value>
</list>
</property>
</bean>
hello = welcome,{0}
now = now is : {1}
hello = 欢迎你, {0}
now = 现在时间是: {1}
使用native2ascii 命令,可以将非西欧文字转换为西欧文字
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
String[] a = {"vivi"};
String hello = ctx.getMessage("hello", a , Locale.getDefault());
Object[] b = {new Date()};
String now = ctx.getMessage("now", b, locale.getDefault);
*********************************************************************