Spring第一天——入门与IOC
大致内容
spring基本概念
IOC入门
【17.6.9更新】,如何学习spring?
掌握用法
深入理解
不断实践
反复总结
再次深入理解与实践
一、Spring相关概念
1.概述:
Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的容器(container)
无论从大小和开销还是来说,都足以称得上是轻量级的框架
由Rod Johnson创建。
简单来说,Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架
可以说,spring带来了复杂JavaEE开发的春天!
【更新】spring是一个解决方案级别的整合框架,主要是用来作解耦
2.核心有两部分:
IOC:控制反转
对象创建不是通过new,而是通过配置交给Spring管理
AOP:面向切面编程
所以AOP的本质是在一系列纵向的控制流程中,把那些相同的子流程提取成一个横向的面
是一种容器,它会管理由他创建的对象,包括生命周期的管理等。
3.一站式框架
在JavaEE三层架构中,每一层都提供了不同的解决方案
web层:SpringMVC
service层:IOC
dao层:jdbcTemplate
对应JavaWeb阶段的三层架构:
4.使用的版本
Spring4.x的版本
5.Spring包的下载方式
http://www.open-open.com/news/view/1eb1613
将文章大致内容提取出来就是:
找到 spring framework
找到All avaible features and modules are described in the Modules section of the reference documentation .
Their maven/gradle coordinates are also described there
这个就是各个spring版本的下载地址: http://repo.spring.io/release/org/springframework/spring 而且很清楚的告诉你下载哪个文件。
(等待maven依赖管理的更新)
二、IOC(Inverse of Control)控制反转
【更新】:面向接口编程 每一层只向外提供接口,各层之间只依赖接口而不依赖具体的实现,用于隐藏具体实现并实现多态的组件
什么被反转了?获得依赖对象的过程被反转了
IOC主要的观点就是借助第三方(也就是IOC容器)实现依赖关系的对象之间的解耦
更多详细的IOC与DI的阐述,请参见:http://www.cnblogs.com/xdp-gacl/p/3707631.html
1.对象创建交给Spring管理
【更新】:应用程序本身并不负责依赖对象的创建和维护,由IOC容器负责创建和维护
(IOC容器初始化的时候会创建一系列的bean,并存在spring的上下文中,ApplicationContext)
2.Ioc管理分为两部分:
【更新,初始化IOC容器的方法(WEB应用中) listen可以通过context-param】 主要是指定 contextConfigLocation
1)Ioc配置文件
2)Ioc注解
(1)==Ioc的底层原理:
主要用到的技术:
xml配置文件
dom4j解析配置文件
工厂设计模式
反射
之前代码:
一个User类:
public class User{
public void add(){
...
}
}
想调用add方法,需要构建类的对象,再调用:
User user = new User();user.add();
如果想在servlet中使用,需要将上述代码写在servlet中,但如果原来的类名、方法名发生了修改
则servlet也要同步修改,耦合度太高,不方便!
针对这种情况,提出第一阶段的解决方案:
工厂模式,使用此模式进行解耦操作
public class UserService{
public void add(){
...
}
}
做法是建立一个工厂类:
public class UserFactory{
//提供静态方法返回
public static UserService getService(){
return new UserService();
}
}
在servlet中调用可以使用工厂:
UserFactory.getService().add();
这样就相对降低了和类的耦合度
但缺陷是和工厂类又有耦合度(高内聚,低耦合)
IOC的解决的大概过程:
要在servlet得到UserService类的实例
步骤:
第一步:创建xml配置文件,配置需要创建的对象的类;
<bean id="userService" class="cn.UserService">
第二步:创建工厂类,使用dom4j解析配置文件+反射
解析xml得到指定id值得class属性值:类路径
采用反射创建类的对象
得到类对象过程还是通过工厂:Factory.getUserService();
此时类名称发生变化时,只需要变更xml配置文件即可
(2)IOC入门案例:
第一步:
导包:jar包里每个都有三个jar包,分别是jar包、doc、源码
spring核心组件有四个(如图)
分别是:beans core context spEL(表达式的,导expression的包)
再导入支持日志输出的jar包(spring本身并不提供日志jar包)【log4j的使用在后面作补充】
log4j logging 两个jar包
也就是如图六个jar包
第二步:
创建类和方法
例如创建User类和add()方法
package cn.ioc; public class User { public void add(){
System.out.println("spring_ioc_add");
}
}
第三步:
创建spring配置文件,配置创建的类
前面两个框架的名称和位置固定,而spring不是,但一般都建议放在src下,【更新】:一般放在与src同级的 source folder 下。
建议名字为 applicationContext.xml
自定义命名请参考:http://huihai.iteye.com/blog/1019281
但完全可以自定义名字(位置建议src!)
在web.xml中指定spring路径:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/beans.xml</param-value>
</context-param>
比如这里创建一个 bean1.xml
创建完xml文件,首先是引入约束(这里是schema约束!)
进入包里的docs->spring framework reference->html->找最后一个文件 (见图!)
【更新】:现在由 springIDE来做这件事
引入schema约束:
<?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.0.xsd"> <!--ioc入门-->
<bean id="user" class="cn.ioc.User"></bean>
</beans>
注意:id建议与类同名,首字母改为小写(这也是spring的默认命名策略)
第四步:
简单测试
步骤:
加载核心配置文件
得到对象
具体不再赘述,见testIoC
package cn.ioc; import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestIoC { //只是测试这样写,实际开发并不这样操作
@Test
public void test(){
//加载spring核心配置文件
ApplicationContext context =
new ClassPathXmlApplicationContext("bean1.xml");
//得到配置创建的对象
User user =(User)context.getBean("user");
user.add();
}
}
//配置文件没有提示的问题(无法上网,类比之前dtd引入,但稍有区别)此处不再赘述,全部在另外一篇同分类引入约束的博客介绍
(3)spring的bean管理(基于配置文件,day02注解方式)
==bean实例化的三种方式:(常用一种方式)
1)使用类的无参构造器(常用)
上面的入门案例
<bean id="user01" class="cn.ioc.User"></bean>
会自动找无参的构造器
2)使用静态工厂创建
在类里使用静态方法返回实例对象
<bean id="user02" class="cn.factory.BeanFactory" factory-method="getBean"></bean>
依旧使用context.getBean()方法得到bean
3)使用实例工厂创建
创建一个不是静态的方法返回类的对象,使用此方式先要创建工厂的对象
<bean id="bean3Factory" class="cn.factory.Bean3Factory"></bean>
<bean id="user03" factory-bean="bean3Factory" factory-method="getBean"></bean>
2、3仅作了解,实际开发用的一般是方式1
==bean标签常用属性的介绍:
id : 表示起的名称(一般不要包含特殊符号) ,可以根据id值得到配置的对象
class : 要创建对象所在类的全路径
name : (一般已经不用了) 功能和id类似,也可以得到bean对象(id值不能得到特殊符号),
属于遗留问题,为了整合原来的struts1的
scope : bean的作用范围:一般掌握两个值:
singleton:单例 (默认)
prototype:多例(应用于struts2的多实例的action)
可以分别拿到两个对象比较对象地址
(4)属性注入:创建对象的时候,也可以向类的属性设置值
属性注入的方式:支持级联属性的注入(但是必须初始化(不会像struts2一样自动创建,当然,很多时候我们都用不着))
原始方式:
有参构造注入
set()方法注入【用的最多】
接口注入(用的少)
spring只支持前两种方式的注入:
spring有参构造注入:
建立类
package cn.propertiry; import java.util.List;
import java.util.Map;
import java.util.Properties; public class PropertiryDemo01 { private String username; public PropertiryDemo01(String username) {
this.username = username;
}
public void print(){
System.out.println("有参构造属性构造:"+username);
} }
配置文件修改:
<!-- 使用有参构造器属性注入 -->
<bean id="prop01" class="cn.propertiry.PropertiryDemo01">
<constructor-arg name="username" value="jiangbei"></constructor-arg>
</bean>
(不出现name属性时,把约束后面的spring-beans-4.0补上)
<!-- 有参构造注入 -->
<bean id="id" class="class">
<!-- name必须和构造器的参数名一致,ref为需要注入的引用 -->
<constructor-arg name="" ref=""/>
</bean>
spring的set方式注入【最常用】:
依旧是:创建类 配置文件配置 简单测试
package cn.propertiry; public class Book { private String BookName;//属性
//set()方法
public void setBookName(String bookName) {
BookName = bookName;
} public void print(){
System.out.println("set属性注入:"+BookName);
}
}
修改配置文件
<!-- set()方法属性注入 -->
<bean id="book" class="cn.propertiry.Book">
<property name="BookName" value="从入门到放弃"></property>
</bean>
【实用】真正开发中不止是注入字符串,更多的是对象的注入等!
例如service中依赖dao,需要dao的属性,可以进行属性注入(只是注入的是对象!)
将new的过程交给spring实现!
先建立两个类 Service Dao
package cn.propertiry; public class Service { //定义dao成员变量
private Dao dao;
public void setDao(Dao dao) {
this.dao = dao;
} public void add(){
//service中要调用dao的add()方法需要得到其对象
dao.add();
}
}
package cn.propertiry; public class Dao { public void add(){
System.out.println("dao.add");
}
}
在Service中依赖dao对象,定义变量,生成set()方法
进行配置(ref):
<!-- 属性注入,注入对象 -->
<bean id="dao" class="cn.propertiry.Dao"></bean>
<!-- 注入dao对象 -->
<bean id="service" class="cn.propertiry.Service">
<!-- name为成员变量名,ref为dao的bean的id -->
<property name="dao" ref="dao"></property>
</bean>
当然是可以通过多行注入多个属性的。
名称空间注入:(也可以实现属性注入)只引出概念,不作演示赘述(用的太少)
===spring注入复杂数据(会用):
例如注入list 注入数组 注入map 注入propertites
都在案例:Prop类里
定义成员
生成set
package cn.propertiry; import java.util.List;
import java.util.Map;
import java.util.Properties; public class Prop { //注入复杂数据类型
private String[] strs;
private List<String> list;
private Map<String,String> map;
private Properties props; public void setStrs(String[] strs) {
this.strs = strs;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProps(Properties props) {
this.props = props;
} public void print2(){
System.out.println("array:"+strs);
System.out.println("list:"+list);
System.out.println("map:"+map);
System.out.println("props:"+props);
}
}
配置注入(所有的注入都必须先有对象(相关数据)生成)
如果是配置引用,可以使用 value-ref等(按alt /即可见名知意)
也可以配置独立的bean(导入util的命名空间),以供多出引用
<!-- 注入复杂属性 -->
<bean id="p" class="cn.propertiry.Prop">
<!-- 进行属性注入 -->
<!-- 数组 -->
<property name="strs">
<list>
<value>sx</value>
<value>sy</value>
<value>sz</value>
</list>
</property>
<!-- list -->
<property name="list">
<list>
<value>lx</value>
<value>ly</value>
<value>lz</value>
</list>
</property>
<!-- map -->
<property name="map">
<map>
<entry key="mx" value="mvx"></entry>
<entry key="my" value="mvy"></entry>
<entry key="mz" value="mvz"></entry>
</map>
</property>
<!-- props -->
<property name="props">
<props>
<!-- props的value值写在标签里 -->
<prop key="px">pvx</prop>
<prop key="py">pvy</prop>
<prop key="pz">pvz</prop>
</props>
</property>
</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.0.xsd"> <!-- bean definitions here ioc入门-->
<bean id="user" class="cn.ioc.User"></bean> <!-- 使用有参构造器属性注入 -->
<bean id="prop01" class="cn.propertiry.PropertiryDemo01">
<constructor-arg name="username" value="jiangbei"></constructor-arg>
</bean> <!-- set()方法属性注入 -->
<bean id="book" class="cn.propertiry.Book">
<property name="BookName" value="从入门到放弃"></property>
</bean>
<!-- 属性注入,注入对象 -->
<bean id="dao" class="cn.propertiry.Dao"></bean>
<!-- 注入dao对象 -->
<bean id="service" class="cn.propertiry.Service">
<!-- name为成员变量名,ref为dao的bean的id -->
<property name="dao" ref="dao"></property>
</bean> <!-- 注入复杂属性 -->
<bean id="p" class="cn.propertiry.Prop">
<!-- 进行属性注入 -->
<!-- 数组 -->
<property name="strs">
<list>
<value>sx</value>
<value>sy</value>
<value>sz</value>
</list>
</property>
<!-- list -->
<property name="list">
<list>
<value>lx</value>
<value>ly</value>
<value>lz</value>
</list>
</property>
<!-- map -->
<property name="map">
<map>
<entry key="mx" value="mvx"></entry>
<entry key="my" value="mvy"></entry>
<entry key="mz" value="mvz"></entry>
</map>
</property>
<!-- props -->
<property name="props">
<props>
<!-- props的value值写在标签里 -->
<prop key="px">pvx</prop>
<prop key="py">pvy</prop>
<prop key="pz">pvz</prop>
</props>
</property>
</bean>
</beans>
【更新】:使用外部属性配置文件(场景就是读取数据源等信息)
之前可以使用此种形式:缺点很明显,如果需要修改数据库的配置信息,将比较复杂,需要拿出spring的配置文件
<!-- 数据库连接池 (此时使用的是dbcp,效率不高,仅作演示使用)-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxActive" value="10" />
<property name="maxIdle" value="5" />
</bean>
我们将这些属性抽取到db.properties:(一般而言,我们都是给Key这里起类似 jdbc.username这样的以.分割的形式,因为有时候直接写username非常容易和其他的(如系统的用户名)相冲突)
jdbc.user=root
jdbc.password=1230
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql:///test jdbc.initPoolSize=5
jdbc.maxPoolSize=10
我们加入context的命名空间(使用springIDE,更简单,更强大!),在配置文件中进行属性文件位置的配置:
<!-- 导入属性文件 -->
<context:property-placeholder location="classpath:db.properties"/>
如何在配置文件中取值我们之前已经提过,使用类似EL的形式:${val}
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="10"/>
<property name="maxIdle" value="5"/>
</bean>
//当然,这些配置都可以通过编码方式来代替,实现真正的全注解无配置开发
【更新】 spring的SpEL:为配置文件动态赋值提供了可能
使用#{...},可以动态引用其它对象,动态引用其它对象的属性值(字面值这里不做阐述)
value="#{car.price}",注解形式:
@Value("#{testConstant.STR}")
private String str;
并且还支持一些基本的运算,以及三目判断运算符等其他的待补充
【更新】 spring容器的生命周期方法:init-method 和 destroy-method
重要概念:
IoC和DI的区别:
IoC:控制反转,将对象的创建交给spring管理
DI:依赖注入,向类的属性中设置值
DI需要在IoC的基础上进行操作(需要在对象创建的基础上进行)
【更新】:DI是IOC的一种更简单的诠释,也就是说:通过引入IOC容器,利用依赖注入的方式,实现对象之间的解耦
【更新】bean的作用域(与struts2整合时使用到)
prototype(每次请求都创建新的实例,使用hashCode判断) singleton request session
bean的生命周期
定义
初始化
(比较简便的配置是bean中配置init-method destroy-method的配置)
当然不使用配置的时候可以通过bean实现 initlizaingBean disposiableBean两个接口,覆盖方法
当然,也可以配置全局的初始化和销毁方法(就近原则 全局的最后执行)
使用
销毁
第一天的最后引出整合的一些基本概述(后面day会做补充)
===spring整合web项目
Hibernate时有一个遗留问题:sessionFactory的创建会比较慢,可以交给服务器来创建
还有上面的bean1.xml每次都要加载spring核心配置文件,会影响性能
以上的类似问题,解决的实现思想都是:
把加载配置文件和创建对象在服务器启动时就创建,把压力给服务器
spring中封装了相关的处理类,这里简单介绍原理:
web阶段中有一个与天地同寿的对象 ServletContext
它的创建可以由监听器进行监听
在服务器启动的时候,服务器会为每个项目创建一个独一无二的对象:ServletContext
可以使用监听器对ServletContext进行监听,可以知道对象的创建时间
于是可以在监听器监听到ServletContext创建后
加载spring配置文件,把配置文件中配置的对象进行创建
对象创建后将创建的对象放在ServletContext中(它也是一个域对象)
域对象的存取数据直接使用get/setAttribute()即可
Spring第一天——入门与IOC的更多相关文章
- Spring入门导读——IoC和AOP
和MyBatis系列不同的是,在正式开始Spring入门时,我们先来了解两个关于Spring核心的概念,IoC(Inverse of Control)控制反转和AOP()面向切面编程. 1.IoC(I ...
- Spring入门2. IoC中装配Bean
Spring入门2. IoC中装配Bean 20131125 前言: 上一节学习了Spring在JavaProject中的配置,通过配置文件利用BeanFactory和ApplicationConte ...
- Spring入门1. IoC入门实例
Spring入门1. IoC入门实例 Reference:Java EE轻量级解决方案——S2SH 前言: 之前学习过关于Spring的一点知识,曾经因为配置出现问题,而总是被迫放弃学习这些框架技术, ...
- Spring第一课:IOC控制反转,什么是反转,什么又是控制?
前言 学习Spring第一课,就是认识IOC控制反转,要了解它还真得花一些功夫.今天主要理解透彻它的真谛,而不仅限于表面. 上道小菜 public class BusinessService { pr ...
- Spring_第一个Spring入门案例IOC
今天我们来写我们的第一个spring 第一步 建立一个java project 第二步 添加我们的五个jar文件 第三步 在项目中建立一个com.zk.spring包 第四步 建立我们的userser ...
- spring jpetstore研究入门(zz)
spring jpetstore研究入门 分类: java2008-12-21 23:25 561人阅读 评论(2) 收藏 举报 springstrutsibatissearchweb框架servle ...
- Spring Boot -01- 快速入门篇(图文教程)
Spring Boot -01- 快速入门篇(图文教程) 今天开始不断整理 Spring Boot 2.0 版本学习笔记,大家可以在博客看到我的笔记,然后大家想看视频课程也可以到[慕课网]手机 app ...
- spring boot入门教程——Spring Boot快速入门指南
Spring Boot已成为当今最流行的微服务开发框架,本文是如何使用Spring Boot快速开始Web微服务开发的指南,我们将使创建一个可运行的包含内嵌Web容器(默认使用的是Tomcat)的可运 ...
- Spring学习笔记(一)—— Spring介绍及入门案例
一.Spring概述 1.1 Spring是什么 Spring是一个开源框架,是于2003年兴起的一个轻量级的Java开发框架, 由Rod Johnson 在其著作<Expert one on ...
随机推荐
- “Validation failed for one or more entities”异常的解决办法
日志中出现Entity Framework修改数据库时的错误: Validation failed for one or more entities. See 'EntityValidationErr ...
- Spring之旅第五篇-AOP详解
一.什么是AOP? Aspect oritention programming(面向切面编程),AOP是一种思想,高度概括的话是“横向重复,纵向抽取”,如何理解呢?举个例子:访问页面时需要权限认证,如 ...
- .Net Webapi SignalR与微信小程序的交互
.Net Webapi SignalR与微信小程序的交互 一.SignalR与Webapi 1.SignalR的安装: Signalr与跨域仅需要安装两个开源库 Microsoft.Owin.Cors ...
- Pi Hybrids问题
Pi Hybrids问题 清华大学肖秀波梁湧老师翻译的Rardin教授的<运筹学>[1]已于今年年中出版,感谢机械工业出版社张有利老师的推荐和赠书,让我能看到如此完美的千页级宏篇译著.该书 ...
- Docker进阶之八:搭建LNMP网站平台实战
搭建LNMP网站平台实战 LNMP是指一组通常一起使用来运行动态网站或者服务器的自由软件名称首字母缩写.L指Linux,N指Nginx,M一般指MySQL,也可以指MariaDB,P一般指PHP,也可 ...
- k8s健康检查(七)--技术流ken
默认的健康检查 强大的自愈能力是 Kubernetes 这类容器编排引擎的一个重要特性.自愈的默认实现方式是自动重启发生故障的容器.除此之外,用户还可以利用 Liveness 和 Readiness ...
- 利用SHA-1算法和RSA秘钥进行签名验签(带注释)
背景介绍 1.SHA 安全散列算法SHA (Secure Hash Algorithm)是美国国家标准和技术局发布的国家标准FIPS PUB 180-1,一般称为SHA-1.其对长度不超过264二进制 ...
- asp.net三层架构增删改查
数据库 use master if exists (select * from sysdatabases where name='bond') drop database bond create da ...
- 【转载】 Sqlserver中通过Select Into语句快速单表备份
在Sqlserver数据库中,备份数据的方式有很多种,可以使用整个数据库备份,也可使用导出包含数据和架构的脚本文件的方式来进行单表或多表数据的备份,其实还有一种Select Into的方式可以快速备份 ...
- [TCP/IP] 网络层-ARP协议
ARP协议可以将网络层地址到任意物理地址转换,从IP地址到MAC地址转换 MAC地址:物理地址,网卡厂家要确保MAC地址全球唯一,48位2进制,显示是12位16进制 1.查看我自己的ip,我自己的的i ...