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调用的方式只需要修改配置文件中的 配置类的路径即可。
3.IOC和DI
IOC
:Inversion of Control 控制反转,将对象的创建权反转交给SpringDI
:Dependency Injection 依赖注入,前提是必须有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="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中配置scope的作用范围
singleton
:默认的,单例模式
创建这个(new一次,用多次),在容器启动时创建
对象,而且只创建一个
。prototype
:多例
模式(用一次就new一个),在容器启动时不创建
对象,当获取对象时创建
。request
: 应用在web项目中,Spring创建这个类以后,将这个类存入request作用域session
:应用在web项目中,Spring创建这个类以后,将这个类存入session作用域globalsession
: 应用在web项目,必须在porlet环境下使用
bean中配置延迟创建对象
只对单例模式有效
lazy-init="true" 延迟创建对象,容器启动时不创建,获取时在创建
lazy-init="false" 不延迟创建对象,容器启动时立即创建
案例
<!--Bean的作用范围的配置,默认情况是单例的,scope="singleton" -->
<bean id="customerDAO"
class="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.构造方法的方式属性的注入
- 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 + "]";
}
}
- 2.配置
<bean id="car" class="spring.demo4.Car">
<constructor-arg name="name" value="宝马"></constructor-arg>
<constructor-arg name="price" value="808080"></constructor-arg>
</bean>
- 3.编写测试类
@Test
//构造方法的属性注入
public void demo1() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car = (Car) applicationContext.getBean("car");
System.out.println(car);
6.2. set方式的属性注入
- 1.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 + "]";
}
}
- 2.配置
<!-- set方法的属性注入方式 -->
<bean id="car2" class="spring.demo4.Car2">
<property name="name" value="奥迪"></property>
<property name="price" value="1000000"></property>
</bean>
- 3.测试方法
@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 + "]";
}
}
- 2.配置文件(重要注释)
<!--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>
配置数据源最常用p
<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
https://www.springframework.org/schema/beans/spring-beans.xsd">
//需要dbcp的jar包哦
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/mydb"
p:username="root"
p:password="123"/>
</beans>
6.4 SpEL表达式的属性注入
<bean id="employee" class="spring.demo4.Employee">
<!--value:设置普通类型的值,ref:设置其他的类的id或name -->
<property name="name" value="#{employee.name}"></property>
<property name="car2" ref="car2"></property>
</bean>
6.5 复杂(集合)属性的注入
6.5.1 Array数组类型属性注入
- 1.编写POJO类
package spring.di;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class Person {
// 数组类型的属性注入
private Object[] cars;
// list类型的属性注入
private List list;
// set类型的属性注入
private Set set;
// Map类型的属性注入
private Map map;
// properties类型的属性注入
private Properties properties;
public Object[] getCars() {
return cars;
}
public void setCars(Object[] cars) {
this.cars = cars;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public Set getSet() {
return set;
}
public void setSet(Set set) {
this.set = set;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "Person [cars=" + Arrays.toString(cars) + ", list=" + list + ", set=" + set + ", map=" + map
+ ", properties=" + properties + "]";
}
}
- 2.配置文件内容
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="personArr" class="spring.di.Person">
<property name="cars">
<array>
<value>自行车</value>
<value>小黄车</value>
<value>公交车</value>
</array>
</property>
</bean>
</beans>
- 3.编写测试类
@Test
public void testPersonArr() {
AbstractApplicatinContext ac = new ClassPathXmlApplicatonContext("applicationContext.xml");
Person person = (Person) ac.getBean("personArr");
System.out.println("person");
}
6.5.2 list集合属性注入
<bean name="personList" class="spring.di.Person">
<property name="list">
<list>
<value>自行车</value>
<value>小黄车</value>
<value>公交车</value>
</list>
</property>
</bean>
@Test
public void testPersonList() {
AbstractApplicatinContext ac = new ClassPathXmlApplicatonContext("applicationContext.xml");
Person person = (Person) ac.getBean("personList");
System.out.println("person");
}
6.5.3 set集合属性注入
<bean name="personset" class="spring.di.Person">
<property name="set">
<set>
<value>set1</value>
<value>set2</value>
<value>set3</value>
</set>
</property>
</bean>
@Test
public void testPersonSet() {
AbstractApplicatinContext ac = new ClassPathXmlApplicatonContext("applicationContext.xml");
Person person = (Person) ac.getBean("personSet");
System.out.println("person");
}
6.5.4 map集合属性注入
<bean name="personMap" class="spring.di.Person">
<property name="map">
<map>
<entry key="username" value="root"></entry>
<entry key="password" value="123456"></entry>
</map>
</property>
</bean>
@Test
public void testPersonMap() {
AbstractApplicatinContext ac = new ClassPathXmlApplicatonContext("applicationContext.xml");
Person person = (Person) ac.getBean("personMap");
System.out.println("person");
}
6.5.5. properties属性注入
<bean name="personPro" class="spring.di.Person">
<property name="properties">
<props>
<prop key="username" value="root"></prop>
<prop key="password" value="123456"></prop>
</props>
</property>
</bean>
@Test
public void testPersonPro() {
AbstractApplicatinContext ac = new ClassPathXmlApplicatonContext("applicationContext.xml");
Person person = (Person) ac.getBean("personPro");
System.out.println("person");
}
7.对象创建的四种方式
- 无参构造函数
- 有参构造函数
- 静态工厂方法
- 实例工厂创建对象
一、创建PersonFactory类
public class PersonFactory{
//静态工厂创建对象
public static Person createPerson1(){
System.out.println("静态工厂创建Person");
return new Person();
}
//实例工厂创建对象
public Person createPerson2(){
System.out.println("实例工厂创建Person");
return new Person();
}
二、在applicationContext.xml中配置
<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:时容器创建Person对象 -->
<!-- name:相当于变量名 Person p =new Person(); -->
<!-- class:类的全路径名 -->
<!-- 静态工厂 -->
<bean id="person1" class="spring.demo1.PersonFactory" factory-method="createPerson1">
<!-- 实例工厂 -->
<bean id="personFactory" class="spring.demo1.PersonFactory">
<bean id="person2" class="spring.demo1.PersonFactory" factory-method="createPerson2">
</beans>
三、测试
@Test
public void createPerson1() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
}