01-spring介绍_
为什么学习 Spring:
方便解耦,简化开发 Spring 就是一个大工厂,可以将所有对象创建和依赖关系维护,交给 Spring 管理 AOP 编程的支持。Spring 提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能 声明式事务的支持 。只需要通过配置就可以完成对事务的管理,而无需手动编程 方便程序的测试 。Spring 对 Junit4 支持,可以通过注解方便的测试 Spring 程序 方便集成各种优秀框架 Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架。(如:Struts、Hibernate、 MyBatis、Quartz 等)的直接支持 降低 JavaEE API 的使用难度 。 Spring 对 JavaEE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等),都提供了封装, 使这些 API 应用难度大大降低。
02-spring项目搭建-导包&对象准备_
第一步 导入jar包
(1)解压资料zip文件
Jar特点:都有三个jar包
(2)做spring最基本功能时候,导入四个核心的jar包就可以了
(3)导入支持日志输出的jar包
第二步 创建类,在类里面创建方法 |
package cn.itcast.bean;
public class User { public User() { System.out.println("User对象空参构造方法!!!!"); } private String name; private Integer age; private Car car; public User(String name, Car car) { System.out.println("User(String name, Car car)!!"); this.name = name; this.car = car; } public User(Car car,String name) { System.out.println("User(Car car,String name)!!"); this.name = name; this.car = car; } public User(Integer name, Car car) { System.out.println("User(Integer name, Car car)!!"); this.name = name+""; this.car = car; } public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public void init(){ System.out.println("我是初始化方法!"); } public void destory(){ System.out.println("我是销毁方法!"); } @Override public String toString() { return "User [name=" + name + ", age=" + age + ", car=" + car + "]"; } } |
第三步 创建spring配置文件,配置创建类
(1)spring核心配置文件名称和位置不是固定的
- 建议放到src下面,官方建议applicationContext.xml
(2)引入schema约束
03-spring项目搭建-约束引入_
04-spring项目搭建-注册对象到容器&测试_
配置文件:建议放到src目录下:
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!-- 将User对象交给spring容器管理 -->
<!-- Bean元素:使用该元素描述需要spring容器管理的对象
class属性:被管理对象的完整类名.
name属性:给被管理的对象起个名字.获得对象时根据该名称获得对象.
可以重复.可以使用特殊字符.
id属性: 与name属性一模一样.
名称不可重复.不能使用特殊字符.
结论: 尽量使用name属性.
-->
<bean name="user" class="cn.itcast.bean.User" ></bean>
<!-- 导入其他spring配置文件 -->
<import resource="cn/itcast/b_create/applicationContext.xml"/>
</beans>
测试类;
package cn.itcast.a_hello;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.itcast.bean.User;
public class Demo {
@Test
public void fun1(){
//1 创建容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//2 向容器"要"user对象
User u = (User) ac.getBean("user");
//3 打印user对象
System.out.println(u);
}
}
05-spring项目概念-IOC&DI_
Spring的IOC底层实现原理
传统方式开发
UserDao userdao = new UserDao();
面向接口编程
UserDao userdao = new UserDaoImpl();
底层实现类的切换
UserDaoImpl 使用JDBC模板
UserDaoHibernateImpl 使用hibernateJdbc模板
切换底层的实现类需要修改程序的源代码
而程序设计中一般遵循一个原则:OCP (Open Closed Principle):
程序设计的时候:尽量做到对程序的扩展是Open 对修改源代码是Closed
好的程序设计应该做到尽量少的修改源代码的基础上,对程序进行扩展。
此时,可以看到接口是实现类多度耦合,每次都要自己创建具体的实现类。所以,此时引入工厂模式。
完成解耦的操作:
BeanFactory对象工厂类似于spring大容器
class BeanFactory{
public static UserDao getUserDao() {
return new UserDaoImpl();
//return new UserDaoHibernateImpl();
}
public static CustomerDao getCustomerDao() {
return new CustomerDaoImpl();
}
}
但是此时接口与工厂又产生了耦合
UserDao userdao = BeanFactory.getUserDao();但是如果我们此时想使用UserDaoHibernateImpl呢?
引入IOC设计思想:工厂+反射+配置文件
第一步 创建xml文件,配置所要创建的对象
<bean name="userDao" class="cn.itcast.dao.UserDao" ></bean>
第二步 创建工厂类,使用dom4j解析技术+反射
class BeanFactory{
//返回userDao对象的方法
public static UserDao getUserDao() {
//使用dom4j技术解析xml文件
//根据id值userDao得到class属性值
String classValue = "类全路径名";
//使用反射创建类对象
Class clazz = Class.forName(classValue);
//创建类对象
UserDao UserDao = clazz.newInstance();
return userDao;
}
}
UserDao UserDao = BeanFactory.getUserDao();
此时当我们想使用不同的实现类时,只需修改配置文件。
IOC inverse of control,控制反转。将我们创建对象的方式反转了,以前对象的创建是由我们开发人员自己维护,包括依赖关系也是自己注入。使用了spring之后,对象的创建及依赖关系可以由spring完成创建以及注入。
控制反转,就是反转了对象的创建方式,从我们自己创建反转给了程序spring。但是,这种思想的实现需要DI技术的支持:
DI;dependency injection 依赖注入
注入方式:
set方法注入
构造方法注入
字段注入
注入类型;
值类型注入 八大基本数据类型
引用类型注入 将依赖关系注入
06-spring项目概念-BeanFactory&ApplicationContext_
BeanFactory:原始接口,针对原始接口的实现类功能较为单一
BeanFactory接口实现类的容器,特点是每次获得对象时,才会创建对象。
//1 创建容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//如果是BeanFactory接口实现类的容器在读取完配置文件之后,并没有创建好对象,而//ApplicationContext已经都创建好了。
//2 向容器"要"user对象
User u = (User) ac.getBean("user");
//3 打印user对象
System.out.println(u);
ApplicationContext:
ApplicationContext在读取完配置文件之后所有配置的对象已经都创建好了,并提供更多功能。它有两个重要的实现类,从类路径下加载配置文件:ClassPathXmlApplicationContext
从硬盘绝对路径下加载配置文件:FileSystemXmlApplicationContext
结论:web开发中,使用applicationContext,在资源匮乏环境下,可以使用BeanFactory.
07-spring配置详解-Bean元素_
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!-- 将User对象交给spring容器管理 -->
<!-- Bean元素:使用该元素描述需要spring容器管理的对象
class属性:被管理对象的完整类名.
name属性:给被管理的对象起个名字.获得对象时根据该名称获得对象.
可以重复.可以使用特殊字符.
id属性: 与name属性一模一样.
名称不可重复.不能使用特殊字符.
结论: 尽量使用name属性.
-->
<bean name="user" class="cn.itcast.bean.User" ></bean>
<!-- 导入其他spring配置文件 -->
<import resource="cn/itcast/b_create/applicationContext.xml"/>
</beans>
08-spring配置详解-三种对象创建方式_
Bean实例化的方式
1 在spring里面通过配置文件创建对象
2 bean实例化三种方式实现
第一种 使用类的无参数构造创建(重点)
<!-- 创建方式1:空参构造创建 -->
<bean name="user" class="cn.itcast.bean.User"
init-method="init" destroy-method="destory" ></bean>
cn.itcast.bean.User一定要有空参构造方法,类里面没有无参数的构造,出现异常:
第二种 使用静态工厂创建
(1)创建静态的方法,返回类对象
准备好cn.itcast.bean.User类,和静态工厂
package cn.itcast.b_create;
import cn.itcast.bean.User;
public class UserFactory {
public static User createUser(){
System.out.println("静态工厂创建User");
return new User();
}
public User createUser2(){
System.out.println("实例工厂创建User");
return new User();
}
}
<!-- 创建方式2:静态工厂创建
调用UserFactory的createUser方法创建名为user2的对象.放入容器
-->
<bean name="user2"
class="cn.itcast.b_create.UserFactory"
factory-method="createUser" ></bean>
第三种 使用实例工厂创建
(1)创建不是静态的方法,返回类对象
准备好cn.itcast.bean.User类,和静态工厂(同上):
<bean name="user3"
factory-bean="userFactory"
factory-method="createUser2" ></bean>
<bean name="userFactory"
class="cn.itcast.b_create.UserFactory" ></bean>
09-spring配置详解-scope属性_
<bean name="user" class="cn.itcast.bean.User" scope="singleton"></bean>
<bean name="user" class="cn.itcast.bean.User" scope="prototype "></bean>
@Test
//scope:singleton 单例
//scope:prototype 多例
public void fun4(){
//1 创建容器对象
ApplicationContext ac =
new ClassPathXmlApplicationContext("cn/itcast/b_create/applicationContext.xml");
//2 向容器"要"user对象
User u = (User) ac.getBean("user");
User u2 = (User) ac.getBean("user");
User u3 = (User) ac.getBean("user");
User u4 = (User) ac.getBean("user");
System.out.println(u2==u4);//单例:true
//多例:false
//3 打印user对象
System.out.println(u);
}
scope属性
- singleton:默认值,单例
- prototype:多例,配置action对象的时候用多例属性值
- request:创建对象把对象放到request域里面
- session:创建对象把对象放到session域里面
- globalSession:创建对象把对象放到globalSession里面
10-spring配置详解-初始化&销毁方法_
准备Customer类和相应的customer对象的创建配置
package cn.itcast.bean;
public class Customer {
public Customer() {
System.out.println("Customer对象空参构造方法!!!!");
}
private String name;
private Integer age;
private Car car;
public Customer(String name, Car car) {
System.out.println("Customer(String name, Car car)!!");
this.name = name;
this.car = car;
}
public Customer(Car car,String name) {
System.out.println("Customer(Car car,String name)!!");
this.name = name;
this.car = car;
}
public Customer(Integer name, Car car) {
System.out.println("Customer(Integer name, Car car)!!");
this.name = name+"";
this.car = car;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void init(){
System.out.println("我是初始化方法!");
}
public void destory(){
System.out.println("我是销毁方法!");
}
@Override
public String toString() {
return "Customer [name=" + name + ", age=" + age + ", car=" + car + "]";
}
}
src目录下applicationContext.xml
<bean name="customer" class="cn.itcast.bean.Customer" init-method="init" destroy-method="destory"></bean>
Customer对象空参构造方法!!!!
我是初始化方法!
Customer [name=null, age=null, car=null]
我是销毁方法!
11-spring配置详解-模块化配置_
在一个主配置文件中引入其他配置文件:
<import resource="cn/itcast/b_create/applicationContext.xml"/>
12-spring配置详解-属性注入(set方式)_
package cn.itcast.bean;
public class User {
public User() {
System.out.println("User对象空参构造方法!!!!");
}
private String name;
private Integer age;
private Car car;
public User(String name, Car car) {
System.out.println("User(String name, Car car)!!");
this.name = name;
this.car = car;
}
public User(Car car,String name) {
System.out.println("User(Car car,String name)!!");
this.name = name;
this.car = car;
}
public User(Integer name, Car car) {
System.out.println("User(Integer name, Car car)!!");
this.name = name+"";
this.car = car;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void init(){
System.out.println("我是初始化方法!");
}
public void destory(){
System.out.println("我是销毁方法!");
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + ", car=" + car + "]";
}
}
package cn.itcast.bean;
public class Car {
private String name;
private String color;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Car [name=" + name + ", color=" + color + "]";
}
}
<!-- set方式注入: -->
<bean name="user" class="cn.itcast.bean.User" >
<!--值类型注入: 为User对象中名为name的属性注入tom作为值 -->
<property name="name" value="tom" ></property>
<property name="age" value="18" ></property>
<!-- 引用类型注入: 为car属性注入下方配置的car对象 -->
<property name="car" ref="car" ></property>
</bean>
<!-- 将car对象配置到容器中 -->
<bean name="car" class="cn.itcast.bean.Car" >
<property name="name" value="兰博基尼" ></property>
<property name="color" value="黄色" ></property>
</bean>
User对象空参构造方法!!!!
User [name=tom, age=18, car=Car [name=兰博基尼, color=黄色]]
13-spring配置详解-属性注入(构造函数)_
<!-- 构造函数注入 -->
<!-- name属性: 构造函数的参数名 -->
<!-- index属性: 构造函数的参数索引 -->
<!-- type属性: 构造函数的参数类型-->
这三个属性可以准确指定通过哪个构造方法进行对象的构造。
<bean name="user2" class="cn.itcast.bean.User" >
<constructor-arg name="name" index="0" type="java.lang.Integer" value="999" >
</constructor-arg>
<constructor-arg name="car" ref="car" index="1" >
</constructor-arg>
</bean>
14-spring配置详解-属性注入(p名称空间&SPEL表达式)_
!-- p名称空间注入, 走set方法
1.导入P名称空间 xmlns:p="http://www.springframework.org/schema/p"
2.使用p:属性完成注入
|-值类型: p:属性名="值"
|-对象类型: p:属性名-ref="bean名称"
-->
<bean name="user3" class="cn.itcast.bean.User" p:name="jack" p:age="20" p:car-ref="car" >
</bean>
<!--
spel注入: spring Expression Language sping表达式语言
-->
<bean name="user4" class="cn.itcast.bean.User" >
<property name="name" value="#{user.name}" ></property>
<property name="age" value="#{user3.age}" ></property>
<property name="car" ref="car" ></property>
</bean>
把user的name赋值给user4的name属性,把user3的age属性值赋值给user4的age属性
15-spring配置详解-复杂类型注入_
package cn.itcast.c_injection;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class CollectionBean {
private Object[] arr;//数组类型注入
private List list;//list/set 类型注入
private Map map;//map类型注入
private Properties prop;//properties类型注入
public Object[] getArr() {
return arr;
}
public void setArr(Object[] arr) {
this.arr = arr;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
public Properties getProp() {
return prop;
}
public void setProp(Properties prop) {
this.prop = prop;
}
@Override
public String toString() {
return "CollectionBean [arr=" + Arrays.toString(arr) + ", list=" + list + ", map=" + map + ", prop=" + prop
+ "]";
}
}
<!-- 复杂类型注入 -->
<bean name="cb" class="cn.itcast.c_injection.CollectionBean" >
<!-- 如果数组中只准备注入一个值(对象),直接使用value|ref即可
<property name="arr" value="tom" ></property>
-->
<!-- array注入,多个元素注入 -->
<property name="arr">
<array>
<value>tom</value>
<value>jerry</value>
<ref bean="user4" />
</array>
</property>
<!-- 如果List中只准备注入一个值(对象),直接使用value|ref即可
<property name="list" value="jack" ></property>-->
<property name="list" >
<list>
<value>jack</value>
<value>rose</value>
<ref bean="user3" />
</list>
</property>
<!-- map类型注入 -->
<property name="map" >
<map>
<entry key="url" value="jdbc:mysql:///crm" ></entry>
<entry key="user" value-ref="user4" ></entry>
<entry key-ref="user3" value-ref="user2" ></entry>
</map>
</property>
<!-- prperties 类型注入 -->
<property name="prop" >
<props>
<prop key="driverClass">com.jdbc.mysql.Driver</prop>
<prop key="userName">root</prop>
<prop key="password">1234</prop>
</props>
</property>
</bean>