Spring体系结构
- 底层是核心容器
- Beans
- Core
- Context
- SpringEl表达式
- 中间层技术
- AOP
- Aspects
- 应用层技术
- 数据访问与数据集成
- Web集成
- Web实现
- 基于Test测试
IoC
- loC (Ilnversion Of Control)控制反转,Spring反向控制应用程序所需要使用的外部资源
- Spring控制的资源全部放置在Spring容器中,该容器称为loC容器
Ioc入门案例制作步骤
- 导入spring坐标(5.1.9.release)
- 编写业务层与表现层(模拟〕接口与实现类
- 建立spring配置文件
- 配置所需资源(Service)为spring控制的资源
- 表现层(App)通过spring获取资源(Service实例)
项目用Maven管理工具创建
在 pom.xml 导入spring坐标
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
</dependencies>
编写业务层与表现层(模拟〕接口与实现类
表现层(模拟〕接口
package com.liu.service;
public interface UserService {
public void save();
}
实现类
package com.liu.service.impl;
import com.liu.service.UserService;
public class UserServiceImpl implements UserService {
public void save() {
System.out.println("user service running...");
}
}
建立spring配置文件
在resources
文件夹下创建applicationContext.xml
文件(规定一定要叫这个名字)
配置所需资源(Service)为spring控制的资源
在applicationContext.xml
文件里
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 创建spring控制的资源 -->
<bean id="userService" class="com.liu.service.impl.UserServiceImpl" />
</beans>
表现层(App)通过spring获取资源(Service实例)
import com.liu.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserApp {
public static void main(String[] args) {
// 2. 加载配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 3.获取资源
UserService userService = (UserService) ctx.getBean("userService");
userService.save();
}
}
Ioc配置(XML格式)
bean
- 名称: bean
- 类型:标签
- 归属: beans标签
- 作用:定义spring中的资源。受此标签定义的资源将受到spring控制
- 格式:
<beans>
<bean />
</beans>
- 基本属性:
id
: bean的名称,通过id值获取beanclass
: bean的类型name
: bean的名称,可以通过name值获取bean,用于多人配合时给bean起别名
<!-- bean可以定义多个名称,使用name属性完成,中间使用,分割 -->
<bean id="userService" name="userService2,userService3" class="com.liu.service.impl.UserServiceImpl" />
调用可以用userService
、userService2
、userService3
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 3.获取资源
UserService userService = (UserService) ctx.getBean("userService2");
bean属性scope
- 名称: scope
- 类型:属性
- 归属: bean标签
- 作用:定义bean的作用范围
- 格式:
<bean scope= "singleton"></bean>
- 取值:
singleton
:设定创建出的对象保存在spring容器中,是一个单例的对象prototype
:设定创建出的对象保存在spring容器中,是一个非单例的对象request
、session
、application
、websocket
:设定创建出的对象放置在web容器对应的位置
设定(singleton)单例对象
<bean id="userService3" scope="singleton" class="com.liu.service.impl.UserServiceImpl" />
// 2. 加载配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 3.获取资源
UserService userService = (UserService) ctx.getBean("userService3");
UserService userService2 = (UserService) ctx.getBean("userService3");
UserService userService3 = (UserService) ctx.getBean("userService3");
System.out.println(userService);
System.out.println(userService2);
System.out.println(userService3);
/*
com.liu.service.impl.UserServiceImpl@5e3a8624
com.liu.service.impl.UserServiceImpl@5e3a8624
com.liu.service.impl.UserServiceImpl@5e3a8624
*/
设定(prototype)非单例对象
有多个个性化的使用时就用非单例对象
<bean id="userService3" scope="prototype" class="com.liu.service.impl.UserServiceImpl" />
// 2. 加载配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 3.获取资源
UserService userService = (UserService) ctx.getBean("userService3");
UserService userService2 = (UserService) ctx.getBean("userService3");
UserService userService3 = (UserService) ctx.getBean("userService3");
System.out.println(userService);
System.out.println(userService2);
System.out.println(userService3);
/*
com.liu.service.impl.UserServiceImpl@5e3a8624
com.liu.service.impl.UserServiceImpl@5c3bd550
com.liu.service.impl.UserServiceImpl@91161c7
*/
bean生命周期
- 名称: init-method,destroy-method
- 类型:属性
- 归属: bean标签
- 作用:定义bean对象在初始化或销毁时完成的工作
- 格式:
<bean init-method="init" destroy-method="destroy"></bean>
- 取值: bean对应的类中对应的具体方法名
- 注意事项:
- 当scope= “singleton”时,spring容器中有且仅有一个对象,init方法在创建容器时仅执行一次
- 当scope= “prototype”时,spring容器要创建同一类型的多个对象,init方法在每个对象创建时均执行一次
- 当scope= "singleton”时,关闭容器会导致bean实例的销毁,调用destroy方法一次
- 当scope= "prototype”时,对象的销毁由垃圾回收机制gc()控制,destroy方法将不会被执行
配置
<!-- init-method与destroy-method用于控制bean的生命周期 -->
<bean id="userService3" init-method="init" destroy-method="destroy" scope="prototype" class="com.liu.service.impl.UserServiceImpl" />
注意: 单例模式只初始化一次,非单例模式 获取多少次就调用多少次初始化函数
引用的是 com.liu.service.impl.UserServiceImpl
实现类,所有两个方法在这个类里实现
package com.liu.service.impl;
import com.liu.service.UserService;
public class UserServiceImpl implements UserService {
public void save() {
System.out.println("user service running...");
}
public void init(){
System.out.println("init..........");
}
public void destroy(){
System.out.println("destroy..........");
}
}
bean对象创建方式(了解)
- 名称: factory-bean
- 类型:属性
- 归属: bean标签
- 作用:定义bean对象创建方式,使用静态工厂的形式创建bean,兼容早期遗留系统的升级工作
- 格式:
<bean class="FactoryClassName" factory-method="factoryMethodName"'></bean>
-
取值:工厂bean中用于获取对象的静态方法名
-
注意事项:
- class属性必须配置成静态工厂的类名
-
名称: factory-bean,factory-method
-
类型:属性
-
归属: bean标签
-
作用:定义bean对象创建方式,使用实例工厂的形式创建bean,兼容早期遗留系统的升级工作
-
格式:
<bean factory-beanm"factoryBeanId" factory-method= "factoryMethodName"></bean>
- 取值:工厂bean中用于获取对象的实例方法名
- 注意事项:
- 使用实例工厂创建bean首先需要将实例工厂配置bean,交由spring进行管理
- factory-bean是实例工厂的beanld
DI
DI(Dependency Injection)依赖注入,应用程序运行依赖的资源由Spring为其提供,资源进入应用程序的方式称为注入
依赖注入的两种方式
set注入(主流)
- 名称:property
- 类型:标签
- 归属:bean标签
- 作用:使用set方法的形式为bean提供资源
- 格式:
<bean>
<property />
</bean>
- 基本属性:
- name:对应bean中的属性名,要求该属性必须提供可访问的set方法(严格规范为此名称是set方法对应名称)
- value:设定非引用类型属性对应的值,不能与ref同时使用
- ref:设定引用类型属性对应bean的id,不能与value同时使用
<property name="propertyName" value="propertyValue" ref="beanId"/>
注入引用类型
创建要引入的dao层
UserDao 接口类
package com.liu.dao;
public interface UserDao {
public void save();
}
UserDaoImpl 实现类
package com.liu.dao.impl;
import com.liu.dao.UserDao;
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("user dao running。。。");
}
}
在Service层里创建对应变量
在 UserServiceImpl 实现类里
package com.liu.service.impl;
import com.liu.dao.UserDao;
import com.liu.service.UserService;
public class UserServiceImpl implements UserService {
private UserDao userDao;
//1.对需要进行储存的变量添加set方法
public void setUserDao(UserDao userDao){
this.userDao=userDao;
}
public void save() {
System.out.println("user service running...");
userDao.save();
}
}
在Spring配置文件里注入
在 applicationContext.xml 配置文件里
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService" class="com.liu.service.impl.UserServiceImpl">
<!-- 3.将要注入的引用类型变量通过property属性进行注入,对应的name是要注入的变量名,使用ref属性声明要注入的bean的id -->
<property name="userDao" ref="userDao" />
</bean>
<!-- 2.将要注入的资源声明为bean -->
<bean id="userDao" class="com.liu.dao.impl.UserDaoImpl" />
</beans>
注入非引用类型
非引用的变量就不用创建dao层
在Service层添创建变量
在 UserServiceImpl 实现类里
private int num;
public void setNum(int num){
this.num=num;
}
在Spring配置文件里注入
不用 注入的资源声明 了直接
<bean id="userService" class="com.liu.service.impl.UserServiceImpl">
<property name="num" value="666"/>
</bean>
构造器注入(了解)
创建要引入的dao层(像上面一样,这里不写了)
在Service层里创建对应变量
在 UserServiceImpl 实现类里
package com.liu.service.impl;
import com.liu.dao.UserDao;
import com.liu.service.UserService;
public class UserServiceImpl implements UserService {
private UserDao userDao;
private int num;
private String version;
public UserServiceImpl(UserDao userDao ,Integer num ,String version){
this.userDao=userDao;
this.num=num;
this.version=version;
}
public void save() {
System.out.println("user service running..."+num +" "+version);
userDao.save();
}
}
在Spring配置文件里注入
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 2.将要注入的资源声明为bean -->
<bean id="userDao" class="com.liu.dao.impl.UserDaoImpl" />
<bean id="userService" class="com.liu.service.impl.UserServiceImpl">
<!-- 使用构造方法进行set注入,需要保障注入的属性与bean中定义的属性一致 -->
<!-- 一致是指顺序一致或类型一致或使用index解决该问题 -->
<constructor-arg name="userDao" ref="userDao" />
<constructor-arg name="num" value="66666" />
<constructor-arg name="version" value="0.0.1" />
</bean>
</beans>
集合类型数据注入
- 名称:array,list, set,map,props
- 类型:标签
- 归属: property标签或constructor-arg标签
- 作用:注入集合数据类型属性
- 格式:
<property>
<list></list>
</property>
创建要引入的dao层
BookDao 接口类
package com.liu.dao;
public interface UserDao {
public void save();
}
BookDaoImpl 实现类
package com.liu.dao.impl;
import com.liu.dao.BookDao;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Properties;
public class BookDaoImpl implements BookDao {
private ArrayList al;
private Properties properties;
private int[] arr;
private HashSet hs;
private HashMap hm;
public void setAl(ArrayList al) {
this.al = al;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public void setArr(int[] arr) {
this.arr = arr;
}
public void setHs(HashSet hs) {
this.hs = hs;
}
public void setHm(HashMap hm) {
this.hm = hm;
}
public void save() {
System.out.println("book dao running。。。。");
System.out.println("ArrayList:"+al);
System.out.println("Properties:"+properties);
for (int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
System.out.println("HashSet:"+hs);
System.out.println("HashMap:"+hm);
}
}
在Service层里创建对应变量
在 UserServiceImpl 实现类里
package com.liu.service.impl;
import com.liu.dao.BookDao;
import com.liu.dao.UserDao;
import com.liu.service.UserService;
public class UserServiceImpl implements UserService {
private BookDao bookDao;
private UserDao userDao;
private int num;
private String version;
public UserServiceImpl() {
}
public UserServiceImpl(UserDao userDao, int num, String version) {
this.userDao = userDao;
this.num = num;
this.version = version;
}
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void setNum(int num) {
this.num = num;
}
public void setVersion(String version) {
this.version = version;
}
public void save() {
System.out.println("user service running..."+num +" "+version);
userDao.save();
bookDao.save();
}
}
在Spring配置文件里注入
在 applicationContext.xml 配置文件里
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- <bean id="userService" class="com.liu.service.impl.UserServiceImpl">-->
<!-- <!– 3.将要注入的引用类型变量通过property属性进行注入,对应的name是要注入的变量名,使用ref属性声明要注入的bean的id –>-->
<!-- <property name="userDao" ref="userDao" />-->
<!-- <property name="num" value="666"/>-->
<!-- </bean>-->
<!-- 2.将要注入的资源声明为bean -->
<bean id="userDao" class="com.liu.dao.impl.UserDaoImpl" />
<bean id="userService" class="com.liu.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
<property name="bookDao" ref="bookDao"/>
</bean>
<bean id="bookDao" class="com.liu.dao.impl.BookDaoImpl">
<property name="al">
<list>
<value>liu</value>
<value>66666</value>
</list>
</property>
<property name="properties">
<props>
<prop key="name">liu</prop>
</props>
</property>
<property name="arr">
<array>
<value>55555</value>
<value>66666</value>
</array>
</property>
<property name="hs">
<set>
<value>liu</value>
<value>66666</value>
</set>
</property>
<property name="hm">
<map>
<entry key="name" value="liu66666"/>
<entry key="value" value="666666666"/>
</map>
</property>
</bean>
</beans>
使用p命名空间简化配置(了解)
- 名称: p:propertyName,p:propertyName-ref类型:属性
- 归属: bean标签
- 作用:为bean注入属性值
- 格式:
<bean p:propertyName="propertyValue" p;propertyName-ref="beanId" />
- 注意:使用p命令空间需要先开启spring对p命令空间的的支持,在beans标签中添加对应空间支持
<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.oxg/sahema/beans
https://www.springiramework.org/schema/beans/spring-beans.xsd">
后续课程中还将开启其他的命名空间,方式同上
<?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">
<!-- 没有用p命名空间前 -->
<bean id="userService" class="com.liu.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
<property name="bookDao" ref="bookDao"/>
</bean>
<!-- 用了p命名空间后 -->
<bean
id="userService"
class="com.liu.service.impl.UserServiceImpl"
p:userDao-ref="userDao"
p:bookDao-ref="bookDao"
/>
</beans>
SpEL
- 所有格式统一使用value="************"
- 常量 #{10} #{3.14} #{2e5} #{‘itcast’’}
- 引用bean #{beanld}
- 引用bean属性 #{beanld.propertyName}
- 引用bean方法 beanld.methodName().method2()
- 引用静态方法 T(java.lang.Math).PI
- 运算符支持 #{ 3 lt 4 == 4 ge 3}
- 正则表达式支持 #{user.name matches ‘[a-z]{6}’ }
- 集合支持 #{likes[3]}
<!-- 使用前 -->
<bean id="userService" class="com.liu.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
<property name="bookDao" ref="bookDao"/>
<property name="num" value="666666"/>
<property name="version" value="0.01"/>
</bean>
<!-- 使用后 -->
<bean id="userService" class="com.liu.service.impl.UserServiceImpl">
<property name="userDao" value="#{userDao}"/>
<property name="bookDao" value="#{bookDao}"/>
<property name="num" value="#{666666}"/>
<property name="version" value