3. Spring概述
3.1. Spring是什么
Spring是一个优秀的高可用的JavaEE轻量级开发框架。提供一站式开发解决方案.
3.2. Spring框架出现的背景
在世界第一套有Java官方Sun公司推出的企业级开发框架EJB出现后,瞬间风靡全球。被各大公司所应用。
Spring之父,Rod Jonhson是一个音乐博士,在Sun公司的大力推广下,也成为EJB框架的使用者。
在深入研究完EJB框架(由Sun主导开发的一个JavaEE开发框架),无法接收这么一个框架被吹成世界第一,具体查看他吐槽EJB的书《Expert one on one J2EE design and development》
其中突出被他吐槽最厉害的一个点就EJB的重量级,就是只要使用EJB里面任何一个组件。都要将所有EJB的jar导进去。
于是他就提供了一个他的解决方案:轻量级的一站式企业开发框架。
那么什么是轻量级呢?
就是除内核模块(4个jar),其他模块由开发者自由选择使用,同时支持整合其他框架。
也可以称为就是可插拔式开发框架,像插头和插座一样,插上就用。这就是Spring框架核心理念。(Ioc)
一站式:
基于MVC开发模式(Model View Controller)
Spring框架提供涵盖了JavaEE开发的表示层,服务层,持久层的所有组件功能。
3.3. Spring框架的作用
根据以上章节的描述。Spring是一个JavaEE一站式的开发框架。它提供的功能涵盖了JavaEE程序中的表示层,服务层,持久层功能组件。这意味着,使用了Spring框架,一个框架就可以满足整个JavaEE程序的开发。
但Spring框架,更加强调的是它的轻量级(模块的可插拔)!!也就是说,除了内核以外模块,如果你不想使用可以不用,它能够整合任何第三方的框架。
所以,在现实开发中,Spring主要用于整合其他框架。
3.4. 总结
- Spring是一个一站式的企业级(JavaEE)开发框架,意味着,仅仅使用一个Spring框架就可以满足JavaEE开发的表示层,服务层,持久层的开发。
- Spring强调的理念是,轻量级。意味着Spring提供的功能模块,除了内核模块以外,开发人员可以选择性使用。
- 所以,Spring框架在现实开发中,主要的功能用于整合,各种开发来开发项目。
3.5. Spring框架包
3.5.1. Maven地址
spring maven两个常用的地址
3.5.1.1 阿里巴巴maven仓库
阿里巴巴的镜像仓库, 可以下载大部分的镜像
<repository> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <layout>default</layout> <snapshots> <enabled>false</enabled> </snapshots> </repository>
3.5.1.2 spring仓库
spring官方仓库, 我之前使用spring cloud的时候阿里云仓库无法下载到一些最新jar, 通过该库可以. 并且速度也非常快
<repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/libs-milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository>
3.5.2. 框架包的下载
地址:http://repo.springsource.org/libs-release-local/org/springframework/spring/
3.5.2. 目录说明
3.5.2.1. --根目录
3.5.2.2. --类库规则
3.5.2.3. --包说明
说明: 红色标注的代表核心功能支撑包,其他的是扩展功能支撑包
包名 | 说明 |
spring-aop-4.2.9.RELEASE.jar | 实现了AOP的支持 |
spring-aspects-4.2.9.RELEASE.jar | AOP框架aspects支持包 |
spring-beans-4.2.9.RELEASE.jar | 内核支撑包,实现了处理基于xml对象存取 |
spring-context-4.2.9.RELEASE.jar | 内核支撑包,实现了Spring对象容器 |
spring-context-support-4.2.9.RELEASE.jar | 容器操作扩展包,扩展了一些常用的容器对象的设置功能 |
spring-core-4.2.9.RELEASE.jar | 内核支撑包,Spring的内核 |
spring-expression-4.2.9.RELEASE.jar | 内核支撑包,实现了xml对Spring表达式的支持 |
spring-instrument-4.2.9.RELEASE.jar | 提供了一些类加载的的工具类 |
spring-instrument-tomcat-4.2.9.RELEASE.jar | 提供了一些tomcat类加载的的工具类,实现对应Tomcat服务的调用 |
spring-jdbc-4.2.9.RELEASE.jar | SpringJDBC实现包,一个操作数据库持久层的子框架 |
spring-jms-4.2.9.RELEASE.jar | 集成jms的支持,jms:Java消息服务。 |
spring-messaging-4.2.9.RELEASE.jar | 集成messaging api和消息协议提供支持 |
spring-orm-4.2.9.RELEASE.jar | ORM框架集成包,实现了Hibernate,IBatis,JDO的集成。 |
spring-oxm-4.2.9.RELEASE.jar | Spring OXM对主流O/X Mapping框架做了一个统一的抽象和封装。就是对应XML读写框架的支持 |
spring-test-4.2.9.RELEASE.jar | Spring集成JUnit测试 |
spring-tx-4.2.9.RELEASE.jar | 事务代理的支持 |
spring-web-4.2.9.RELEASE.jar | SpringWeb通用模块 |
spring-webmvc-4.2.9.RELEASE.jar | SpringMVC子框架 |
spring-webmvc-portlet-4.2.9.RELEASE.jar | Spring对门户技术(portlet)的支持 |
spring-websocket-4.2.9.RELEASE.jar | Spring对websocket的支持 |
4. 入门示例
要实现Ioc(控制反转)的前提,是不用new就可以创建对象。而Spring是一个Ioc框架。所以我们首先需要证明使用Spring框架,不用new就可以创建对象。
这个不用new就可以创建对象,用术语来数据,就叫依赖注入!!
需求:使用Spring框架不用new创建一个对象。
4.1. 配置流程图
创建一个普通的类
- 创建一个Spring配置文件,用于描述类与类之间的关系。
- 创建ApplicationContext容器对象根据Spring配置文件的描述,将对象创建并且放在Spring容器里面。
- 使用ApplicationContext容器对象的getBean方法,调用Spring容器里面的对象。
4.2. 配置步骤说明
- 导入包
- 创建一个普通的类
- 创建一个Spring配置文件(通过xsd规则文件生成)
问题1:配置文件为什么使用的是XML
答:答因为XML的是格式的,这个格式可以让开发工具有提示功能
问题:Eclipse为什么需要xsd或者dtd
答:因为开发工具Eclipse必须要有XML的规则文件(dtd、sxd)才可以对相关的配置文件进行提示
问题:Eclipse如果没有Spring框架对应的规则文件,怎么办?
答:需要手工配置上去。我们必须要学会配置规则文件到Eclipse!!!
- 编写一个测试类,使用ApplicationContext的子类对象根据配置文件创建容器。并且在容器里面获得创建的对象
4.3. 配置步骤
4.3.1. 第一步:搭建环境
1.创建一个Java项目
--选中创建
2.导入包,String的基础支撑包和依赖的日志包复制到lib文件下,并且加入项目中
---导入Spring基础支撑包
--导入Spring依赖的日志包,这个jar包可以在struts2框架包中找到
4.3.2. -第二步:创建配置文件
问题:为什么我们大部分的框架的配置文件是XML文件?
答:因为XML文件可以让内容有格式(标签);
问题:XML是通过什么东西来约束标签的?
答:XML是通过规则文件来约束标签的。XML的规则文件有两种,DTD、Schema。
结论:任何框架只有提供了XML配置文件,必要要提供配置文件的规则文件!!
问题:为什么我们要在Eclipse里面配置XML的规则文件?
答:因为Eclipse这些开发工具,可以通过配置XML的规则文件(DTD、Schema),通过规则文件生成配置文件以及让配置文件有提示!!!!
- 首先在Eclipse配置xsd规则文件
--我们知道,要Eclipse通过规则文件生成配置文件,必须在Eclipse里面配置规则文件
--Spring配置类与类之间关系使用的规则文件为:spring-beans-*.xsd
--放在spring安装包schema/beans目录下
--spring.schemas文件里面存放的Schema location路径,在spring-beans-4.3.7.RELEASE.jar 包的/META-INF/spring.schemas目录下--Eclipse配置xsd规则文件
问题:为什么我们的schema location 需要使用spring.schemas声明的路径?
答:Spring框架必须验证xsd规则文件Schema location的路径是否有效,目的是为了关联本地的规则文件。 如果schema location和spring.schemas文件的一致,Spring会自动的读取本地包里面的xsd来验证,如果不一致就会根据schema location配置的路径去互联网检查下载,如果网络不通就会报错!!
我们不希望Spring框架联网检查xsd的有效,而是直接检查自身jar里面自带的xsd。所以配置的路径必须要和spring.schemas声明的一致!!!
- 使用Eclipse配置好的规则文件创建applicationContext.xml配置文件
--选择生成的属性
4.3.3. 第三步:创建对象到容器里面
- 创建一个类
package cn.gzsxt.service;
public class HelloWorldService {
public void say(){ System.out.println("--你好世界!--"); }
}
|
- applicationContext.xml配置文件加入配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!-- <bean>标签:用于声明一个类,在启动Spring框架的时候根据该配置的类创建对象到容器里面 name
--> <bean name="helloWorldService" class="cn.gzsxt.service.HelloWorldService"></bean> </beans> |
- 测试使用getBean获得容器中的对象。
package cn.gzsxt.test;
import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.gzsxt.service.HelloWorldService;
public class HelloWorldServiceTest {
@Test public void say(){ //创建一个ApplicationContext对象,根据xml配置创建一个对象 //直接读取Spring的src目录下的配置文件的子类是ClassPathXmlApplicationContext ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); HelloWorldService helloWorldService = context.getBean("helloWorldService", HelloWorldService.class); //调用方法 helloWorldService.say(); //结束程序,可以关闭容器 context.close(); } }
|
通过代码得到,Spring框架果然不用new就可以创建对象。
4.3.4. 注意事项
在Eclipse工具配置Spring的xsd规则文件的要求。
必须配置的location要和spring.schemas保持一致。否则会联网检查,如果连不上网络会报错。
--从spring.schemes复制location过来,要去掉\
4.4. Spring容器的两个实现
ClassPathXmlApplicationContext:通过classpath路径直接获得加载的xml文件(推荐使用)
FileSystemXmlApplicationContext:通过文件路径来获得加载的xml文件。
4.5. ApplicationContext类图结构图(了解)
通过结构图可以看到,Spring容器顶级接口是BeanFactory,ApplicationContext是它的子接口。
5. 使用STS开发Spring程序
由于Spring的配置文件较多,基于Eclipse配置也比较复杂。为了提高开发的效率,建议使用STS开发工具开发,或者在Eclipse安装一个STS插件。
通过STS插件,配置文件可以直接通过工具管理,不需要做过多的配置。
在Eclipse安装STS插件:
方式1:通过Eclipse自带的插件市场联网安装。
![]()
|
--安装
方式2:直接下载一个和Eclipse对应版本的sts开发工具,将sts的plugins文件覆盖eclipse的 plugins文件夹。
下载路径:https://spring.io/tools
第一步:
第二步:https://spring.io/tools/sts/legacy
--将下好的STS的插件文件夹,覆盖eclipse的插件文件夹
注意:覆盖前一定要确认sts对应Eclipse的版本。
![]()
|
6. IoC(控制反转)的概述
Spring号称是一个可以实现模块可插拔(轻量级)的JavaEE开发框架。那么它是如何实现程序的可插拔的呢?
实现程序可以插拔的核心理念就是,控制反转(Inversion of Control,英文缩写为IoC)
所谓的控制反转,就是将代码的调用权(控制权)从调用方转移给被调用方(服务提供方)。
如图所示:
- 强耦合调用方式
将A调用B的对象修改为C类的对象,修改的是调用方的代码,所以我们认为代码的调用权在调用方。
![]()
|
- 基于IoC(控制反转)的调用方式
将上图的需求,修改为使用Ioc的调用代码方式。就是将代码的控制权从调用方修改为被调用方,意味着,代码的调用权转移给被调用方(我们也称为服务方),不用修改调用方的的代码
只要修改配置文件就实现对象的切换。
如下图:将A类调用B类的对象修改为C类的对象,修改的是被调用方的配置文件的代码,所以代码的调用权转移到了被调用方。通过控制反转,我们可以实现增加模块或者移除模块统一由配置文件关联,增加或者移除模块,配置XML配置文件即可。
我们将代码的调用权(控制权)从调用方转移给被调用方(服务提供方)的设计模式称为控制反转(IoC)
![]()
|
根据上图可以的得出,实现一个IoC的框架,必须要解决两个问题:
1.被调用方(服务方),在程序启动时就要根据配置文件类与类的关系创建好对象,放在一个容器里面。
2.调用方使用一个接口或类的引用(不用使用new),就可以创建获得对象。
我们将这种不用new,而是根据接口或者类的引用就可以从被调用的容器里获得创建的对象的方式称为依赖注入。
所以,控制反转(Ioc)=就是依赖注入加上面向接口的编程思想的实现。
在这里,我们首先抓住一个重点:Spring之所以可以实现可插拔程序,是实现了不用new,使用类或接口就可以获得获得对象!
7. 基于Spring框架的IoC实现
7.1. 说明需求
CustomerClient调用CustomerService的save()方法。将调用CustomerServiceImpl的对象实现的save()切换成调用CustomerServiceImpl2对象实现的save()。
注意:重点观察CustomerClient,切换过程中有没有修改该类的代码。
7.2. 需求修改说明图
![]()
|
如果将CustomerClient调用的CustomerServiceImpl的对象修改为CustomerServiceImpl2的对象,而不用修改CustomerClient的代码。那么说明代码的调用权限从CustomerClient转移到了服务方。
7.3. 项目目录结构
7.4. 示例代码
- CustomerService接口代码
package cn.gzsxt.service;
public interface CustomerService { /** * 保存方法 */ public void save();
} |
- CustomerServiceImpl子类
package cn.gzsxt.service.impl;
import cn.gzsxt.service.CustomerService;
public class CustomerServiceImpl implements CustomerService{
@Override public void save() { System.out.println("-保存客户-CustomerServiceImpl");
}
}
|
- CustomerServiceImpl2子类
package cn.gzsxt.service.impl;
import cn.gzsxt.service.CustomerService;
public class CustomerServiceImpl2 implements CustomerService{
@Override public void save() { System.out.println("-保存客户-CustomerServiceImpl2");
}
}
|
- CustomerClient类(调用方)
package cn.gzsxt.client;
import cn.gzsxt.service.CustomerService;
public class CustomerClient {
//1.声明一个父接口的引用 private CustomerService customerService;
//2.使用set方法注入对象,我们将通过方法注入的对象的方式称为依赖注入 public void setCustomerService(CustomerService customerService) { this.customerService = customerService; }
public void login(){ //调用服务端的方法 customerService.save();; }
}
|
- 配置文件applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!-- <bean>标签:用于声明一个类,在启动Spring框架的时候根据该配置的类创建对象到容器里面 name --> <!-- <bean name="customerServiceImpl" class="cn.gzsxt.service.impl.CustomerServiceImpl"></bean> --> <!-- CustomerServiceImpl修改为CustomerServiceImpl2的配置 --> <bean name="customerServiceImpl" class="cn.gzsxt.service.impl.CustomerServiceImpl2"></bean>
<bean name="customerClient" class="cn.gzsxt.client.CustomerClient"> <!-- 对应set方法关联的对象 customerService name:关联对应的set方法,关联规则:xxx对应setXxx();如:customerService() 对应setCustomerService() ref:指向容器中的对象 --> <property name="customerService" ref="customerServiceImpl"></property> </bean> </beans>
|
- 测试代码
package cn.gzsxt.test;
import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.gzsxt.client.CustomerClient;
public class ClientTest {
@Test public void save(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); CustomerClient customerClient = context.getBean("customerClient", CustomerClient.class); //调用方法 customerClient.login();
}
}
|
7.测试结果
![]()
|
8. 标签说明
8.1. alias标签
作用:为已配置的bean设置别名
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" name="test" class="cn.gzsxt.entity.User"/>
<!-- 标签alias: 为已配置的bean设置别名 属性name: 必要属性, 代表为哪一个bean配置别名, 此属性的值为其他bean标签的id或name属性值 属性alias: 必要属性, 代表新命名的别名是什么 --> <alias name="user" alias="user1"/>
</beans>
|
--测试代码
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.gzsxt.entity.User;
public class Test { public static void main(String[] args) { // 读取Spring配置文件 ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml");
// 通过id获取User对象 User user = (User) context.getBean("user"); // 测试对象 System.out.println(user); System.out.prntln("====================================="); // 通过alias获取User对象 user = (User) context.getBean("user1"); // 测试对象 System.out.println(user); } } |
8.2. bean标签的配置
8.2.1. bean标签作用
用于声明一个类,在启动Spring框架的时候根据该配置的类创建对象到容器里面
8.2.2. 属性说明
<!-- <bean>标签:用于声明一个类,在启动Spring框架的时候根据该配置的类创建对象到容器里面 name:设置对象名(唯一标识符) id:设置对象名(唯一标识符,功能和name一样) class:用于指定对象对应的类名,如果不是实现类必须要将bean声明为抽象的!!! scope:用于设置的对象的作用范围,可选参数如下: *singleton:单例(默认) 对象出生:当程序加载配置文件创建容器时,创建 对象活着:只要容器还在,一直活着 对象死亡:应用停止,容器销毁,对象死亡 *prototype:多例(原型对象) 对象出生:当程序加载配置文件创建容器时,创建,(每次调用会创建一个新对象) 对象活着:只要对象被使用,一直活着 对象死亡:对象长时间不用,会被Java垃圾回收机制回收 (该对象不被容器管理) *reqeust:web项目中,Spring将创建的对象放在request作用域中 *session:web项目中,Spring将创建的对象放在session作用域中 init-method:设置创建对象的时候,调用初始化方法 destroy-method:设置对象被回收时,调用注销的方法
--> <bean name="customerServiceImpl" class="cn.gzsxt.service.impl.CustomerServiceImpl"></bean>
|
8.2.3. Bean作用范围
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "> <bean name="customerDAOImpl" class="cn.gzsxt.dao.impl.CustomerDAOImpl"></bean> <!-- 原型对象:prototype 单例:singleton(默认) --> <bean name="customerService" scope="singleton" class="cn.gzsxt.service.CustomerService"> <property name="customerDAO" ref="customerDAOImpl"></property> </bean>
<!-- <bean name="customerService" scope="prototype" class="cn.gzsxt.service.CustomerService"> --> <!-- <property name="customerDAO" ref="customerDAOImpl"></property> --> <!-- </bean> --> </beans> |
8.3. 实例化Bean的四种方式
8.3.1. 通过class直接创建
<bean name="customerService" class="cn.gzsxt.service.CustomerService"> |
8.3.2. 通过静态方法工厂创建(了解)
--静态工厂类
package cn.gzsxt.factory;
import cn.gzsxt.service.CustomerService;
public class CreateFactory {
/** * 使用一个静态工厂类,通过字符串创建一个对象 * * @param className * @return */ public static Object create() {
return new CustomerService();
}
} |
--静态工厂配置
<bean name="customerService" factory-method="create" class="cn.gzsxt.factory.CreateFactory"> <property name="customerDAO" ref="customerDAOImpl"></property> </bean> |
8.3.3. 通过实体工厂创建(了解)
--实体工厂,注意create方法没有static
package cn.gzsxt.factory;
import cn.gzsxt.service.CustomerService;
public class CreateFactory {
/** * 使用一个静态工厂类,通过字符串创建一个对象 * * @param className * @return */ public Object create() {
return new CustomerService();
}
}
|
--配置方式
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "> <bean name="customerDAOImpl" class="cn.gzsxt.dao.impl.CustomerDAOImpl"></bean> <!--非静态的方法,必须需要对象来调用,所以必须要创建工厂类的对象 --> <bean name="createFactory" class="cn.gzsxt.factory.CreateFactory" ></bean> <bean name="customerService" factory-method="create" factory-bean="createFactory" > <property name="customerDAO" ref="customerDAOImpl"></property> </bean> </beans>
|
8.3.4. 内置FactoryBean工厂创建对象的实现
Spring支持一种,通过实现FactoryBean的接口创建工厂类对象。必须返回泛型指定的类型的对象。
public class HelloWorldServiceFactory implements FactoryBean<HelloWorldService> {
/** * 返回创建的对象 */ @Override public HelloWorldService getObject() throws Exception { return new HelloWorldService(); }
/** * 返回对象的类型 */ @Override public Class<?> getObjectType() { return HelloWorldService.class; }
/** * 是否是单例,如果是true ,否则就是false */ @Override public boolean isSingleton() { return false; }
} |
--调用代码
package cn.gzsxt.test;
import org.junit.Test; import org.springframework.beans.BeansException; import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.gzsxt.service.HelloWorldService;
public class HelloWorldTest {
@Test public void say() {
try { //Spring框架的路径格式:如果从包里面开始读取的路径,使用classpath开始 ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); //对象名必须要和配置的对象名一一对应 HelloWorldService helloWorldService = applicationContext.getBean("helloWorldService", HelloWorldService.class); helloWorldService.say(); applicationContext.close(); } catch (BeansException e) { // TODO Auto-generated catch block e.printStackTrace(); }
}
}
|
FactoryBean创建对象的应用场景,有这么一种情况,创建好的对象需要设置很多参数再返回。
我们而且这些参数我们每次创建对象都必须要先设置的。那么我们可以通过一个工厂类对象创建,必须设置好参数。这样就可以将参数和对象打包了!!
我们经常看见框架整合的时候,会看到FactoryBean接口创建的对象。因为框架调用的时候经常涉及参数与对象绑定在一起!!!!
9. Spring依赖注入(重点)
所谓的依赖注入,就是属性不用new创建对象,通过配置文件的配置将Spring容器里面的对象注入给对应的属性。
9.1. set方法注入
--类代码
package cn.gzsxt.service;
import java.util.Date;
public class CustomerService {
private int age; private String name; private Date birthDate;
public void setAge(int age) { this.age = age; }
public void setName(String name) { this.name = name; }
public void setBirthDate(Date birthDate) { this.birthDate = birthDate; }
public void reigster(){ System.out.println("姓名:"+name); System.out.println("年龄:"+age); System.out.println("生日:"+birthDate); }
}
|
配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "> <bean name="now" class="java.util.Date"></bean> <bean name="customerService" class="cn.gzsxt.service.CustomerService"> <!-- 一个property标签匹配一个set方法 --> <!-- 只要是标量类型,可以使用value设置, 注意:所谓的标量类型就是基础数据类型(以及包装类)+String类型 如果非标量类型,必须使用ref引用对象 --> <property name="name" value="张三"></property> <property name="age" value="15"></property> <property name="birthDate" ref="now"></property> </bean> </beans>
|
9.2. 构造方法注入
--类的实现
package cn.gzsxt.service;
import java.util.Date;
public class CustomerService {
private int age; private String name; private Date birthDate;
/** * 声明一个有参数的构造方法 * @param age * @param name * @param birthDate */ public CustomerService(int age, String name, Date birthDate) { super(); this.age = age; this.name = name; this.birthDate = birthDate; }
public void reigster(){ System.out.println("姓名:"+name); System.out.println("年龄:"+age); System.out.println("生日:"+birthDate); }
}
|
--对应配置文件的配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "> <bean name="now" class="java.util.Date"></bean> <bean name="customerService" class="cn.gzsxt.service.CustomerService"> <!-- 构造函数每一个参数:对应一个constructor-arg标签 name:指定参数名 value:指定注入的值 ref:指定引用的对象 index:指定参数的位置 type:指定参数的数据库类型,默认使用参数声明的类型【可以忽略】
--> <constructor-arg name="age" value="15"></constructor-arg> <constructor-arg name="name" type="java.lang.String" value="张三"></constructor-arg>
<constructor-arg name="birthDate" ref="now"></constructor-arg>
<!-- 通过位置指定参数 --> <!-- <constructor-arg index="0" value="15"></constructor-arg> --> <!-- <constructor-arg index="1" value="张三"></constructor-arg> --> <!-- <constructor-arg index="2" ref="now"></constructor-arg> -->
</bean> </beans> |
9.3. 使用p标签注入属性(了解)
--类代码
package cn.gzsxt.service;
import java.util.Date;
public class CustomerService {
private int age; private String name; private Date birthDate;
public void setAge(int age) { this.age = age; }
public void setName(String name) { this.name = name; }
public void setBirthDate(Date birthDate) { this.birthDate = birthDate; }
public void reigster(){ System.out.println("姓名:"+name); System.out.println("年龄:"+age); System.out.println("生日:"+birthDate); }
}
|
--配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "> <bean name="now" class="java.util.Date"></bean> <bean name="customerService" class="cn.gzsxt.service.CustomerService" p:name="张三" p:age="15" p:birthDate-ref="now"> </bean> </beans>
|
9.4. 注入集合数据
在处理的数据中,
有标量类型=基础数据类型以及包装类+String -- value属性
也有Spring容器里面的对象 --ref属性
还要很多数据JDK内置的数据结构:
- 键值对 Map <map>、Properties <prop>
- 数组 <array>
- 集合Set <set>、List <list>
--类代码
package cn.gzsxt.service;
import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set;
public class CustomerService {
private String[] myStrs; private List<String> myList; private Set<String> mySet; private Map<String,Object> myMap; private Properties myProps;
public void setMyStrs(String[] myStrs) { this.myStrs = myStrs; }
public void setMyList(List<String> myList) { this.myList = myList; }
public void setMySet(Set<String> mySet) { this.mySet = mySet; }
public void setMyMap(Map<String, Object> myMap) { this.myMap = myMap; }
public void setMyProps(Properties myProps) { this.myProps = myProps; }
public void reigster(){ System.out.println(Arrays.toString(myStrs)); System.out.println(myList); System.out.println(mySet); System.out.println(myMap); System.out.println(myProps); }
}
|
--配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "> <bean name="now" class="java.util.Date"></bean> <bean name="customerService" class="cn.gzsxt.service.CustomerService">
<property name="myStrs"> <array> <value>AAA</value> <value>BBB</value> <value>CCC</value> </array> </property> <property name="mySet"> <set> <value>AAA</value> <value>BBB</value> <value>CCC</value> </set> </property> <property name="myList"> <list > <value>AAA</value> <value>BBB</value> <value>CCC</value> </list> </property> <property name="myMap"> <map> <entry key="id" value="1" /> <entry key="name" value="张三"></entry> <entry key="birthDate" value-ref="now"></entry>
</map> </property> <property name="myProps"> <props> <prop key="id" >1</prop> <prop key="name">张三</prop>
</props> </property> </bean> </beans>
|
注意事项:集合与数组的标签可以互相调换是使用的。但是不建议调换使用
10. 获得Properties文件的值
10.1. 说明
Spring配置文件支持通过Properties文件的Key获得对应的值。实现该功能是通过
- PropertySourcesPlaceholderConfigurer指定Properties的路径
- 通过${Key}来获得Properties文件对应Key的值
10.2. 示例代码
10.2.1. 第一步:创建项目导入包
![]()
|
10.2.2. 第二步:编写一个普通的CustomerService类
package cn.gzsxt.service;
import java.util.Date;
public class CustomerService {
private int age; private String name; private Date birthDate;
public void setAge(int age) { this.age = age; }
public void setName(String name) { this.name = name; }
public void setBirthDate(Date birthDate) { this.birthDate = birthDate; }
public void reigster(){ System.out.println("姓名:"+name); System.out.println("年龄:"+age); System.out.println("生日:"+birthDate); } } |
10.2.3. 第三步:编写Properties文件键值对
注意:默认必须是ISO-8859-1编码,
customer.age = 20 customer.name =\u5F20\u4E09 |
--如果需要其他编码,需要设置
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"> <!-- 指定加载的Properties的文件路径 --> <property name="locations" value="classpath:sys.properties"></property> <!-- 注意:默认是ISO-8859-1编号,如果要使用其他编码,需要设置 --> <property name="fileEncoding" value="UTF-8"></property> </bean> |
10.2.4. 第四步:编写配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd "> <bean name="now" class="java.util.Date"></bean> <bean name="customerService" class="cn.gzsxt.service.CustomerService"> <!-- 一个property标签匹配一个set方法 --> <property name="name" value="${customer.name}"></property> <property name="age" value="${customer.age}"></property> <property name="birthDate" ref="now"></property> </bean>
<!-- 配置指定Properties的路径 --> <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"> <property name="locations" value="classpath:customer.properties"></property> </bean> </beans> |
10.2.5. 第五步:测试
package cn.gzsxt.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.gzsxt.service.CustomerService;
public class CustomerServiceTest {
public static void main(String[] args) { ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("bean.xml");
CustomerService customerService = context.getBean("customerService",CustomerService.class); customerService.reigster(); context.close(); }
}
|
--测试结果,可以获得Properties文件的值,测试成功
![]()
|
11. 总结
- 怎样的程序架构是一个好架构
答:可维护性好,可扩展性好,性能好
- 如何能够让程序的可维护性好(高内聚),可扩展性好(低耦合)?
答:标准:高内聚,低耦合
- 扩展好的体现是什么
答:编写的程序,在增加新的代码以后,不需要修改原来的代码!!!
- 我们有是什么办法可以提高程序的可扩展性呢?
答:对程序进行解耦!!
- 程序解耦,有什么解决解方案。
答:IOC (控制反转)
- 6. Ioc是什么意思?(重点)
答:Ioc是一种设计理念(理论)。将代码的控制权从调用方,转移到被调用方
通过Ioc,我们实现了,需要某个模块,就可以在配置文件增加整合的配置,如果不需要了,就可以在配置文件移除。不会影响原来的代码!!
- Ioc的实现的前提必须要有依赖注入。依赖注入是什么意思呢?
答:所谓的依赖注入,就是我们的对象可以不使用new,而是通过配置文件的类与类的关系
(<property><construtor-arg>)来注入对象获得数组给类的属性。
注意:Spring基于XML的依赖注入,如果使用<property>,必须要有一个对应的set方法。
- 如果理解了Ioc的作用。我们剩下的内容就是对配置文件标签的理解
<alias>
<bean>
<property>
<constructor-arg>
<array>
<list>
<set>
<map>
<entry>
<props>
<prop>
<value>
<context:property-placeholder>
p命名空间
根据以上的线索,我们知道spring以后就是用于整合其他框架的。
Spring概述
Spring是一个一站式、轻量级、J2EE的框架。
通过这句话,
我们知道Spring首先就是Ioc理念的实现(轻量级)。
Spring是一个功能很齐全的框架,(一站式,全家桶)