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 ...
随机推荐
- 你真的了解webview么?
你真的了解webview么? 写在前面: Webview是我们前端开发从PC端演进到移动端的一个重要载体,现在大家每天使用的App,webview都发挥着它的重要性.接下来让我们从webview看世界 ...
- 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十四 ║ VUE 计划书 & 我的前后端开发简史
---新内容开始--- 番外 大家周一好呀,又是元气满满的一个周一呀!感谢大家在周一这个着急改Bug的黄金时期,抽出时间来看我的博文哈哈哈,时间真快,已经到第十四篇博文了,也很顺顺(跌跌)利利 (撞撞 ...
- C# 《编写高质量代码改善建议》整理&笔记 --(五)类型设计
1.区分接口和抽象类的应用场合 区别: ①接口支持多继承,抽象类则不能. ②接口可以包含方法,属性,索引器,事件的签名,但不能有实现,抽象类则可以. ③接口在增加新方法后,所有的继承者都必须重构,否则 ...
- FragmentTabHostTopDemo【FragmentTabHost固定宽度且居中】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 使用FragmentTabHost实现顶部选项卡(居中且宽度非全屏)展现. 备注:该Demo主要是演示FragmentTabHost ...
- EF Core利用Scaffold从根据数据库生成代码
在EF6 之前的时代,如果需要从数据库中生成代码,是可以直接在界面上操作的,而到了EF Core的时代,操作方式又有更简便的方式了,我们只需要记住以下这条指令. Scaffold-DbContext ...
- Vue Mixin 与微信小程序 Mixins 应用
什么是Mixin(混入) Mixin是一种思想,用来实现代码高度可复用性,可以针对属性复制实现代码复用的想法进行一个扩展,就是混入(mixin).混入并不是复制一个完整的对象,而是从多个对象中复制出任 ...
- 浅析HttpSession
苏格拉底曰:我唯一知道的,就是自己一无所知 源头 最近在翻阅Springboot Security板块中的会话管理器过滤器SessionManagementFilter源码的时候,发现其会对单用户的多 ...
- Spring Boot 2.x(十一):AOP实战--打印接口日志
接口日志有啥用 在我们日常的开发过程中,我们可以通过接口日志去查看这个接口的一些详细信息.比如客户端的IP,客户端的类型,响应的时间,请求的类型,请求的接口方法等等,我们可以对这些数据进行统计分析,提 ...
- KVM虚拟化使用详解--技术流ken
KVM介绍 Kernel-based Virtual Machine的简称,是一个开源的系统虚拟化模块,自Linux 2.6.20之后集成在Linux的各个主要发行版本中. KVM的虚拟化需要硬件支持 ...
- asp.net Core HttpClient 出现Cannot access a disposed object. Object name: 'SocketsHttpHandler' 的问题。
ASP.NET Core 部署在Centos 中 偶尔出现 One or more errors occurred. (Cannot access a disposed object.Object n ...