Spring IOC
Spring框架是一个开源的javaEE的应用程序
主要核心是IOC(控制反转/依赖注入)和aop(面向切面编程)两大技术。
1.Spring作用
2.Sping IOC
3.Spring环境搭建
1. 创建普通的Maven项目 (修改pom.xml配置文件)
2. 在pom.xml中引入spring框架的依赖坐标
Maven仓库:https://mvnrepository.com/
<!-- 添加Spring框架的核⼼依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
3. 创建Bean对象
4. 在resources目录下新建spring.xml配置文件,并设置bean标签
并拷⻉官⽹⽂档提供的模板内容到 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">
<!--
xmlns 即 xml namespace xml使⽤的命名空间
xmlns:xsi 即xml schema instance xml 遵守的具体规范
xsi:schemaLocation 本⽂档xml遵守的规范 官⽅指定
-->
<bean id="userService" class="com.xxxx.service.UserService"></bean>
</beans>
id: bean标签的唯一标识,一般是对应的JavaBean对象名称的首字母小写
class: JavaBean对象的类路径(包名+类名)
5. 得到spring的上下文环境,通过getBean方法得到指定id的bean对象
public class App {
public static void main(String[] args) {
// 获取Spring上下⽂环境 (加载配置⽂件)
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
// 通过getBean⽅法得到Spring容器中实例化好的Bean对象 (实例化Bean对象)
// userService代表的是配置⽂件中bean标签的id属性值
UserServer userService = (UserServer) ac.getBean("userServer");
// 调⽤⽅法 (使⽤实例化对象)
userService.show();
}
}
运行成功:
4.Spring IOC 容器 Bean 对象实例化
1. 构造器实例化
注:通过默认构造器创建 空构造⽅法必须存在 否则创建失败
- 设置配置⽂件 spring.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.xxxx.service.UserService"></bean>
</beans>
- 获取实例化对象
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) ac.getBean("userService");
userService.test();
Spring三种实例化Bean的⽅式⽐较
⽅式⼀:通过bean的缺省构造函数创建,当各个bean的业务逻辑相互⽐较独⽴的时候或者和外界
关联较少的时候可以使⽤。
⽅式⼆:利⽤静态factory⽅法创建,可以统⼀管理各个bean的创建,如各个bean在创建之前需要
相同的初始化处理,则可⽤这个factory⽅法险进⾏统⼀的处理等等。
⽅式三:利⽤实例化factory⽅法创建,即将factory⽅法也作为了业务bean来控制,1可⽤于集成其
他框架的bean创建管理⽅法,2能够使bean和factory的⻆⾊互换。
开发中项⽬⼀般使⽤⼀种⽅式实例化bean,项⽬开发基本采⽤第⼀种⽅式,交给Spring托管,使⽤时
直接拿来使⽤即可。另外两种了解
5.Spring IOC注入
5.1手动注入
以往调用dao层方法:手动实例化
set方法注入
Spring ⽀持的注⼊⽅式共有四种:set 注⼊、构造器注⼊、静态⼯⼚注⼊、实例化⼯⼚注⼊。
四种⽅式,推荐使⽤set⽅法注⼊,这边只展示set方法注入
----大家主要掌握业务对象javaBean即可,后面的常用对象等类型了解即可----
当存在两个bean对象时,一个bean需要调用另一个bean,需要set方法注入:
Set方法注入
1.属性字段提供set方法
2.在配置文件中通过property属性指定属性字段
常⽤对象和基本类型
//1. 属性字段提供 set ⽅法
public class UserService {
// 常⽤对象String set注⼊(提供set⽅法)
private String host;
public void setHost(String host) {
this.host = host;
}
// 基本类型Integer set注⼊(提供set⽅法)
private Integer port;
public void setPort(Integer port) {
this.port = port;
}
}
- 配置⽂件的 bean 标签设置 property 标签
<?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">
<!--
IOC通过property标签⼿动装配(注⼊):
Set⽅法注⼊
name:bean对象中属性字段的名称
value:具体的值(基本类型 常⽤对象|⽇期 集合)
-->
<bean id="userService" class="com.xxxx.service.UserService">
<!-- 常⽤对象String 注⼊ -->
<property name="host" value="127.0.0.1"/>
<!-- 基本类型注⼊ -->
<property name="port" value="8080"/>
</bean>
</beans>
实现调用:
集合类型和属性对象
- 属性字段提供set⽅法
public class UserService {
// List集合 set注⼊(提供set⽅法)
public List<String> list;
public void setList(List<String> list) {
this.list = list;
}
// Set集合 set注⼊(提供set⽅法)
private Set<String> set;
public void setSet(Set<String> set) {
this.set = set;
}
// Map set注⼊(提供set⽅法)
private Map<String,Object> map;
public void setMap(Map<String, Object> map) {
this.map = map;
}
// Properties set注⼊(提供set⽅法)
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
}
- 配置⽂件的bean标签设置property标签
<?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.xxxx.service.UserService">
<!--List集合 注⼊-->
<property name="list">
<list>
<value>上海</value>
<value>北京</value>
<value>杭州</value>
</list>
</property>
<!--Set集合注⼊-->
<property name="set">
<set>
<value>上海SH</value>
<value>北京BJ</value>
<value>杭州HZ</value>
</set>
</property>
<!--Map注⼊-->
<property name="map">
<map>
<entry>
<key><value>周杰伦</value></key>
<value>我是如此相信</value>
</entry>
<entry>
<key><value>林俊杰</value></key>
<value>可惜没如果</value>
</entry>
<entry>
<key><value>陈奕迅</value></key>
<value>⼗年</value>
</entry>
</map>
</property>
<!--Properties注⼊-->
<property name="properties">
<props>
<prop key="上海">东⽅明珠</prop>
<prop key="北京">天安⻔</prop>
<prop key="杭州">⻄湖</prop>
</props>
</property>
</bean>
</beans>
测试代码
// List集合输出
public void printList() {
list.forEach(s -> System.out.println(s));
}
// Set集合输出
public void printSet() {
set.forEach(s -> System.out.println(s));
}
// Map输出
public void printMap() {
map.forEach((k,v) -> System.out.println(k + "," + v));
}
// Properties输出
public void printProperties(){
properties.forEach((k,v) -> System.out.println(k + ","+ v ));
}
public void test(){
System.out.println("UserService Test...");
userDao.test();
studentDao.test();
System.out.println("Host:" + host + ",port:" + port);
// List集合
printList();
// Set集合
printSet();
// Map
printMap();
// Properties
printProperties();
}
在配置⽂件 spring.xml 引⼊ p 名称空间
xmlns:p="http://www.springframework.org/schema/p"
//可以将 ⼦元素,简化为元素属性配置。
5.2IOC自动注入
**注解⽅式注⼊ Bean**
对于 bean 的注⼊,除了使⽤ xml 配置以外,可以使⽤注解配置。注解的配置,可以简化配置⽂件,
提⾼开发的速度,使程序看上去更简洁。对于注解的解释,Spring对于注解有专⻔的解释器,对定义的
注解进⾏解析,实现对应bean对象的注⼊。通过反射技术实现。
环境准备
1:新建一个maven项目
2.把没有的删掉
3.修改基本的配置
4.引入spring的依赖环境坐标
5.新建两个包,包下一个实现类,里面写一个测试方法
**
6.修改配置⽂件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启⾃动化装配(注⼊)-->
<context:annotation-config/>
<bean id="userDao" class="org.example.dao.UserDao"></bean>
<bean id="userService" class="org.example.server.UserServer"></bean>
</beans>
7.测试
@Resource注解
@Resource注解实现⾃动注⼊(反射)
- 默认根据属性字段名称查找对应的 bean 对象 (属性字段的名称与bean标签的id属性值相等)
- 如果属性字段名称未找到,则会通过类型(Class类型)查找
- 属性可以提供set⽅法,也可以不提供set⽅法
- 注解可以声明在属性级别 或 set⽅法级别
- 可以设置name属性,name属性值必须与bean标签的id属性值⼀致;如果设置了name属性值,就只
会按照name属性值查找bean对象 - 当注⼊接⼝时,如果接⼝只有⼀个实现则正常实例化;如果接⼝存在多个实现,则需要使⽤name
属性指定需要被实例化的bean对象
@Autowired注解
@Autowired注解实现⾃动化注⼊:
- 默认通过类型(Class类型)查找bean对象 与属性字段的名称⽆关
- 属性可以提供set⽅法,也可以不提供set⽅法
- 注解可以声明在属性级别 或 set⽅法级别
- 可以添加@Qualifier结合使⽤,通过value属性值查找bean对象(value属性值必须要设置,且值要与
bean标签的id属性值对应)
推荐使⽤@Resource 注解是属于J2EE的,减少了与Spring的耦合。
6.Spring IOC扫描器
实际的开发中,bean的数量⾮常多,采⽤⼿动配置bean的⽅式已⽆法满⾜⽣产需要,Spring这时候同
样提供了扫描的⽅式,对扫描到的bean对象统⼀进⾏管理,简化开发配置,提⾼开发效率。
Spring IOC 扫描器
作⽤:bean对象统⼀进⾏管理,简化开发配置,提⾼开发效率
1、设置⾃动化扫描的范围
如果bean对象未在指定包范围,即使声明了注解,也⽆法实例化
2、使⽤指定的注解(声明在类级别) bean对象的id属性默认是 类的⾸字⺟⼩写
Dao层:
@Repository
Service层:
@Service
Controller层:
@Controller
任意类:
@Component
注:开发过程中建议按照指定规则声明注解
- 设置⾃动化扫描范围
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 设置⾃动化扫描的范围 -->
<context:component-scan base-package="com.xxxx"/>
</beans>
- 使⽤特定的注解
3.main方法打印
7.Spring 模拟⽤户登录流程
-
快速搭建一个maven项目,引入spring依赖
-
配置好spring.xml文件,设置⾃动化扫描
-
做一个分层
-
实体类
- 编写Dao层 UserDao.java
package com.xxxx.dao;
import com.xxxx.po.User;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
private final String USERNAME = "admin";
private final String USERPWD = "admin";
/**
* 通过⽤户名称查询⽤户对象
* @param userName
* @return
*/
public User queryUserByUserName(String userName){
User user = null;
// 判断⽤户名称是否正确
if(!USERNAME.equals(userName)){
// 如果不正确,返回null
return null;
}
// 如果正确,将⽤户名称和密码设置到user对象中
user = new User();
user.setUserName(USERNAME);
user.setUserPwd(USERPWD);
return user;
}
}
- Service层 (业务逻辑处理)
1.定义业务处理返回消息模型 MessageModel.java
/**
* 定义业务处理返回消息模型
* 封装返回结果
*/
public class MessageModel {
private Integer resultCode = 1; // 结果状态码 1=成功,0=失败
private String resultMsg = "操作成功!"; // 结果提示信息
public Integer getResultCode() {
return resultCode;
}
public void setResultCode(Integer resultCode) {
this.resultCode = resultCode;
}
public String getResultMsg() {
return resultMsg;
}
public void setResultMsg(String resultMsg) {
this.resultMsg = resultMsg;
}
}
2.编写Service层 UserService.java
@Service
public class UserService {
@Resource
private UserDao userDao;
/**
* 验证⽤户登录
* @param userName
* @param userPwd
* @return
*/
public MessageModel userLoginCheck(String userName, String userPwd){
// 定义业务处理返回消息模型
MessageModel messageModel = new MessageModel();
// 判断⽤户名称是否⾮空
if(null == userName || "".equals(userName.trim())){
messageModel.setResultCode(0);
messageModel.setResultMsg("⽤户名不能为空!");
return messageModel;
}
// 判断⽤户密码是否为空
if(null == userPwd || "".equals(userPwd.trim())){
messageModel.setResultCode(0);
messageModel.setResultMsg("密码不能为空!");
return messageModel;
}
// 通过⽤户名称查询⽤户对象
User user = userDao.queryUserByUserName(userName);
// 判断⽤户对象是否为空
if(null == user){
messageModel.setResultCode(0);
messageModel.setResultMsg("该⽤户不存在!");
return messageModel;
}
// 如果⽤户对象不为空,判断密码是否正确
if(!user.getUserPwd().equals(userPwd)){
messageModel.setResultCode(0);
messageModel.setResultMsg("⽤户密码不正确!");
return messageModel;
}
// 登录成功
messageModel.setResultMsg("登录成功!");
return messageModel;
}
}
- Controller层 (接收请求)
1.编写Controller层 UserController.java
@Controller
public class UserController {
@Resource
private UserService userService;
/**
* ⽤户登录
* @param userName
* @param userPwd
* @return
*/
public MessageModel login(String userName, String userPwd){
// 调⽤Dao层判断⽤户登录操作,返回结果
MessageModel messageModel = userService.userLoginCheck(userName,
userPwd);
return messageModel;
}
}
- 通过 JUnit 进⾏测试
public class TestLogin {
@Test
public void test() {
// 得到Spring容器上下⽂环境
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
// 得到UserController实例化对象
UserController userController = (UserController) ac.getBean("userController");
// 传⼊参数调⽤UserController的⽅法,返回封装类
MessageModel messageModel= userController.login("admin", "admin");
System.out.println("状态码:" + messageModel.getResultCode() + ",提示信息:" +
messageModel.getResultMsg());
}
}
8.Bean的作用域
singleton 作⽤域
- 什么是⽆状态或状态不可改变的对象?
实际上对象状态的变化往往均是由于属性值得变化⽽引起的,⽐如user类 姓名属性会有变化,属性姓
名的变化⼀般会引起user对象状态的变化。对于我们的程序来说,⽆状态对象没有实例变量的存在,保
证了线程的安全性,service 层业务对象即是⽆状态对象。线程安全的。
9.bean的生命周期
在Spring中,Bean的⽣命周期包括Bean的定义、初始化、使⽤和销毁4个阶段
10.IOC总结
IOC/DI-控制反转和依赖注入
将对象实例化的创建过程转交给外部容器(IOC容器充当工厂角色)去负责;属性赋值的操作;