1. Spring的概述
1.1 什么是Spring?
- Spring的核心是控制反转(IoC)和面向切面(AOP)。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。
1.2 Spring框架的优点
- 方便解耦,简化开发 (高内聚低耦合)
Spring就是一个大工厂(容器),可以将所有对象创建和依赖关系维护,交给Spring管理 ,spring工厂是用于生成bean
- AOP编程的支持
Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
- 声明式事务的支持
只需要通过配置就可以完成对事务的管理,而无需手动编程
- 方便程序的测试
Spring对Junit4支持,可以通过注解方便的测试Spring程序
- 方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持
- 降低JavaEE API的使用难度
Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低
2. 什么是IOC?
- IOC:Inversion of Control
控制反转:将对象的创建权反转交给Spring容器,控制权由对象本身转向Spring容器;由Spring容器根据配置文件去创建实例并创建各个实例之间的依赖关系
3. Spring的入门
- 3.1 spring 官网:
- Spring的目录结构与介绍
- docs : Spring的开发规范和API
- libs : Spring的开发的jar包和源码
- scheme : Spring的配置文件的约束
- Spring的项目搭建
- 导入jar包
导入四个核心jar包即可,需要日志文件的化需要导入日志文件的jar包,不需要的化四个就够了。
- Spring的底层的实现原理
- 编写一个接口类
package spring.demo1;
//用户管理业务层的接口
public interface UserDAO {
public void save();
}
- 编写一个实现类
package spring.demo1;
public class UserDAOImpl implements UserDAO {
@Override
public void save() {
System.out.println("UserDAOImpl执行了" );
}
}
- 编写Spring的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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">
<!-- Spring的入门配置 -->
<bean id="userDAO" class="spring.demo1.UserDAOImpl">
</bean>
</beans>
- 编写测试类比较传统方式的调用与Spring方式的调用
package spring.demo1;
//Spring 的入门
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringDemo1 {
//传统方式的调用,可以输出结果
@Test
public void demo1() {
UserDAOImpl us = new UserDAOImpl();
us.save();
}
// Spring方式的调用,输出同样的结果,通过配置文件去调用
@Test
public void demo2() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDAO userDAO = (UserDAO) applicationContext.getBean("userDAO");
userDAO.save();
}
}
- 两者的区别,传统方式的调用如果改变需要修改源代码,而Spring调用的方式只需要修改配置文件中的 配置类的路径即可。
IOC和DI
IOC:控制反转,将对象的创建权反转交给Spring
- DI:依赖注入,前提是必须有IOC环境,Spring管理这个类的时候将类的依赖属性注入(设置)进来。
package spring.demo1;
public class UserDAOImpl implements UserDAO {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public void save() {
System.out.println("UserDAOImpl DI属性注入" + name);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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">
<!-- Spring的入门配置 -->
<bean id="userDAO" class="spring.demo1.UserDAOImpl">
<!--DI属性注入 -->
<property name="name" value="haha"></property>
</bean>
</beans>
package spring.demo1;
//Spring 的入门
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringDemo1 {
// Spring方式的调用
@Test
public void demo2() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDAO userDAO = (UserDAO) applicationContext.getBean("userDAO");
userDAO.save();
}
}
4 Spring的工厂类介绍
- BeanFactory : 老版本的工厂类
在调用getBean的时候,才会生成类的实例
- ApplicationContext :新版本的工厂类
- ApplicationContext :加载配置文件的时候,就会将Spring管理的类都实例化
- ApplicationContext有两个实现类
- ClassPathXmlApplicationContext :加载类路径下的配置文件
- FileSystemXmlApplicationContext :加载文件系统下的配置文件(硬盘上的文件)
@Test
public void demo2() {
//加载类路径下的配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDAO userDAO = (UserDAO) applicationContext.getBean("userDAO");
userDAO.save();
}
@Test
public void demo3() {
//加载文件系统下的配置文件(硬盘上的配置文件)
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("C:\\applicationContext.xml");
UserDAO userDAO = (UserDAO) applicationContext.getBean("userDAO");
userDAO.save();
}
- ApplicationContext和BeanFactory的区别?
- Spring的工厂类结构图
5. Spring的配置文件的各类属性
5.1 Bean标签的相关属性详解
- id : 使用约束中的唯一约束,里面不能出现特殊字符
- name : 没有使用约束中的唯一约束(理论上是可以出现重复的,但是实际开发不会出现),里面可以出现特殊字符
- class : 需要被Spring管理的类的全路径
5.2 Bean 的生命周期的配置(了解)
- 1.编写实类
package spring.demo2;
public class CustomerDAOImpl implements CustomerDAO {
//此处省略CustomerDAO的编写,和入门案例一样的
public void setup() {
System.out.println("CustomerDAOImpl被初始化了。。");
}
@Override
public void save() {
System.out.println("CustomerDAOImpl的save方法执行了。。");
}
public void destroy() {
System.out.println("CustomerDAOImpl的destroy销毁了。。");
}
}
- 编写配置文件,重点在这里,看配置文件的各个属性
<bean id="customerDAO"
class="com.itheima.spring.demo2.CustomerDAOImpl"
init-method="setup" destroy-method="destroy">
</bean>
- 生命周期的测试类
@Test
public void demo1() {
// 用第一个不能执行销毁的方法
// ApplicationContext applicationContext = new
// ClassPathXmlApplicationContext("applicationContext.xml");
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
CustomerDAO customerDAO = (CustomerDAO) applicationContext.getBean("customerDAO");
customerDAO.save();
applicationContext.close();
}
- init-method :Bean被初始化的时候执行的方法
- destroy-method : Bean被销毁的时候执行的方法
5.3 Bean的作用范围的配置(重点)
scope 属性:Bean的作用范围
-
singleton :默认的,单例模式创建这个(new一次,用多次)
-
prototype :多例模式(用一次就new一个)
-
request : 应用在web项目中,Spring创建这个类以后,将这个类存入request作用域
-
session :应用在web项目中,Spring创建这个类以后,将这个类存入session作用域
-
globalsession : 应用在web项目,必须在porlet环境下使用
-
案例
<!--Bean的作用范围的配置,默认情况是单例的,scope="singleton" -->
<bean id="customerDAO"
class="com.itheima.spring.demo2.CustomerDAOImpl"
init-method="setup" destroy-method="destroy">
</bean>
- 单例(默认)测试类
@Test
public void demo2() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
CustomerDAO customerDAO1 = (CustomerDAO) applicationContext.getBean("customerDAO");
System.out.println(customerDAO1);
CustomerDAO customerDAO2 = (CustomerDAO) applicationContext.getBean("customerDAO");
System.out.println(customerDAO2);
System.out.println(customerDAO1 == customerDAO2);
applicationContext.close();
结果是true ,两次new创建出来的实例是一样的
- 多例模式,想一下?需要在配置文件中配置scope=“prototype” ,再次运行测试类,会发现两次创建的是不一样的实例。
6. Spring的属性注入
6.1.构造方法的方式属性的注入
- 编写构造方法类
package spring.demo4;
public class Car {
private String name;
private Double price;
public Car(String name, Double price) {
super();
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "Car [name=" + name + ", price=" + price + "]";
}
}
- 配置
<bean id="car" class="spring.demo4.Car">
<constructor-arg name="name" value="宝马"></constructor-arg>
<constructor-arg name="price" value="808080"></constructor-arg>
</bean>
- 编写测试类
@Test
//构造方法的属性注入
public void demo1() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car = (Car) applicationContext.getBean("car");
System.out.println(car);
6.2. set方式的属性注入
- set方法类的编写
package spring.demo4;
public class Car2 {
private String name;
private Double price;
public void setName(String name) {
this.name = name;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public String toString() {
return "Car2 [name=" + name + ", price=" + price + "]";
}
}
- 配置
<!-- set方法的属性注入方式 -->
<bean id="car2" class="spring.demo4.Car2">
<property name="name" value="奥迪"></property>
<property name="price" value="1000000"></property>
</bean>
- 测试方法
@Test
//set方法的属性注入
public void demo2() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Car2 car2 = (Car2) applicationContext.getBean("car2");
System.out.println(car2);
6.2.2 set方法设置对象类型的属性注入
package spring.demo4;
public class Employee {
private String name;
private Car2 car2;
public void setName(String name) {
this.name = name;
}
public void setCar2(Car2 car2) {
this.car2 = car2;
}
@Override
public String toString() {
return "Employee [name=" + name + ", car2=" + car2 + "]";
}
}
- 配置文件(重要注释)
<!--set方法注入对象类型的属性 -->
<bean id="employee" class="spring.demo4.Employee">
<!--value:设置普通类型的值,ref:设置其他的类的id或name -->
<property name="name" value="xiabaobao"></property>
<property name="car2" ref="car2"></property>
</bean>
- 测试方法
@Test
public void demo3() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Employee employee = (Employee) applicationContext.getBean("employee");
System.out.println(employee);
}
6.3 P 名称空间的属性注入
- 通过引入P名称空间完成属性的注入
- 写法
普通属性 P:属性名=“值“
对象属性 P :属性名-ref=“值”
- 第一步: p的设置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
- 第二,注入普通类型的属性
<bean id="car2" class="spring.demo4.Car2" p:name="奔驰"
p:price="300000"></bean>
- 测试
public void demo2() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Car2 car2 = (Car2) applicationContext.getBean("car2");
System.out.println(car2);
}
- 假如注入对象类型的属性
<bean id="employee" class="spring.demo4.Employee"
p:name="xiabaobao" p:car2-ref="car2"></bean>
6.4 SpEL的属性注入
看文档吧