Spring系列笔记一——IOC(控制反转)/DI(依赖注入)

IOC-控制反转

  • 概念:指的是将对象的创建权交给 Spring 去创建
  • 作用:通过Spring创建对象可实现依赖注入
  • 创建对象的方式:
    1. 无参构造
    2. 有参构造
    3. 工厂模式
  • Bean:在 Spring 中,被 Spring 容器所管理的对象称之为”Bean”对象。一个 Spring 的 Bean 对象 可以是任何形式的 POJO

Spring IOC 容器类型

Spring提供了两种IOC容器,分别为BeanFactory和ApplicationContext

BeanFactory

BeanFactory是基础类型的IOC容器
它由 org.springframework.beans.facytory.BeanFactory 接口定义,并提供了完整的 IoC 服务支持。简单来说,BeanFactory 就是一个管理 Bean 的工厂,它主要负责初始化各种 Bean,并调用它们的生命周期方法

ApplicationContext

ApplicationContext 是 BeanFactory 的子接口,也被称为应用上下文。该接口的全路径 为 org.springframework.context.ApplicationContext,它不仅提供了 BeanFactory 的所有功能, 还添加了对国际化、资源访问、事件传播等方面的良好支持

  • ApplicationContext 接口有两个常用的实现类
    ClassPathXmlApplicationContext类
//该 类 从 类 路 径 ClassPath 中 寻 找 指 定 的 XML 配 置 文 件 , 找 到 并 装 载 完 成 ApplicationContext 的实例化工作
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(String configLocation);
//FileconfigLocation 参数用于指定 Spring 配置文件的名称和位置

FileSystemXmlApplicationContext类

//该类从指定的文件系统路径中寻找指定的 XML 配置文件,找到并装载完成 ApplicationContext 的实例化工作
ApplicationContext applicationContext = new FileSystemXmlApplicationContext(String configLocation)

区别:在读取 Spring 的配置文件时, FileSystemXmlApplicationContext 不再从类路径中读取配置文件,而是通过参数指定配置文 件的位置,它可以获取类路径之外的资源,如“F:/workspaces/applicationContext.xml”

简单范例

添加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 10
http://www.springframework.org/schema/beans/spring-beans.xsd"> </beans>

通过 IOC 容器管理 Bean 对象

  • 创建接口及其实现类
public interface UsersService { void addUsers(); }

public class UsersServiceImpl implements UsersService { 
	@Override 
	public void addUsers() { 
		System.out.println("UsersService addUsers ......"); 
	} 
}
  • 修改配置文件,在Spring配置文件下,添加:
<bean id="usersService" class="com.lanh.service.impl.UsersServiceImpl"/> </beans>
  • 获取IOC容器中的对象
public class UsersServiceTest { public static void main(String[] args) { 
//启动 Spring IOC 容器 
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); 
//从 IOC 容器中获取 
UsersService usersService = (UsersService) applicationContext.getBean("usersService"); usersService.addUsers(); }

创建 Bean 对象的三种方式

通过构造方法创建Bean对象

public class UsersServiceImpl implements UsersService{
	public UsersServiceImpl(){
		System.out.println("Init");
	}

	@Override
	public void addUsers(){
		System.out.println("UsersService addUsers");
	}
}

通过静态工厂方法创建对象

  • 创建静态工厂方法
public class ObjectFactory { 
	public static UsersService getInstance(){
		return new UsersServiceImpl();
	}
}
  • 修改配置文件
<!--通过静态工厂方法实例化对象--> 
<bean id="usersService" class="com.lanh.factory.ObjectFactory" factory-method="getInstance"/> </beans>

factory-method必须是静态方法

  • 创建测试类
public class Test{
	public static void main(String[] args){
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml")
		UsersService usersService = (UsersService)applicationContext.getBean("usersService");
		usersService.addUsers();
	}
}

通过动态工厂方法创建对象

  • 创建动态工厂方法
public class DynamicObjectFactory{
	public UsersService getInstance(){
		return new UsersServiceImpl();
	}
}
  • 修改配置类
<!--通过动态工厂方法实例化对象--> 
<bean id="dynamicObjectFactory" class="com.lanh.factory.DynamicObjectFactory"/> 
<bean id="usersService" factory-bean="dynamicObjectFactory" factory-method="getInstance"/>
  • 创建测试类
public class DynamicFactoryTest { 
	public static void main(String[] args) { 
	ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); 
	UsersService usersService = (UsersService) applicationContext.getBean("usersService"); 
	usersService.addUsers(); 
	} 
}

三种方法的区别

  • 第一种:通过默认的无参构造方法创建,本质是将类交给Spring自带的工厂BeanFactory管理,由Spring自带的工厂模式帮我们维护和创建这个类
  • 第二种:通过静态工厂创建,其本质是将类交给我们自己的静态工厂管理,Spring仅仅是帮助我们调用静态方法创建实例的方法
  • 第三种:通过实例工厂创建,本质就是把创建实例的工厂类交由Spring管理,同时将调用工厂类的方法创建实例的这个过程也交由Spring管理

获取Bean对象的方式

通过id或name获取Bean对象

applicationContext.getBean(id|name);

  • 配置文件
<bean id="usersService" name="name1,name2,name3" class="com.lanh.service.impl.UsersServiceImpl"/>
  • 获取bean对象
UsersService usersService = (UsersService) applicationContext.getBean("name2");

getBean中可填usersService.name1,name2,name3均可得到Bean对象

通过类型获取Bean对象

applicationContext.getBean(Class class)

通过类型来或取 Bean 时,要求类型必须是唯一的

  • 获取bean对象
//通过类型获取 Bean 对象 
UsersService usersService = applicationContext.getBean(UsersServiceImpl.class); 
usersService.addUsers();

通过 id 或 name获取Bean对象

在 SpringIOC 容器中,通过类型获取对象时,如果同一类型存在多个对象,我们可以使 用 id 或 name 来识别需要获取的对象

  • 方式一
UsersService usersService = applicationContext.getBean("name1",UsersServiceImpl.class); 
usersService.addUsers();
  • 方式二
//获取 Spring IOC 容器中所有的 Bean 对象的 ID 
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); 
for(String name: beanDefinitionNames){ 	
	System.out.println(name); 
}
UsersService usersService = applicationContext.getBean(beanDefinitionNames[0],UsersServiceImpl.class); 
usersService.addUsers();

SpringIOC容器创建对象的策略

Bean的作用域

作用域:作用域限定了 Spring Bean 的作用范围,在 Spring 配置文件定义 Bean 时,通过 声明 scope 配置项,可以灵活定义 Bean 的作用范围
scope的值:

  • singleton
  • prototype
singleton

singleton 为 scope 属性的默认值。当 scope 属性的值为 singleton 时,Spring IOC 容器启 动时会立即实例化一次 Bean 对象,并一直被 Spring IOC 容器所缓存,所以生命周期较长。
特点:

  • Spring IOC容器启动时会创建Bean对象
  • 每次调用getBean都返回Spring容器中唯一一个对象
prototype

当 scope 属性的值为 prototype 时,每次调用调用 getBean 方法时都会返回一个新的 Bean 对象,Spring IOC 容器并不会缓存该对象,所以就不再负责管理它的生命周期
特点:

  • Spring IOC容器启动时不会创建Bean对象
  • 每次调用getBean都会创建一个新Bean对象

实例化对象策略

Spring IOC 容器在启动时默认的会将在配置文件中所配置的所有 Bean 对象立即进行实 例化,并保存在 IOC 容器中。我们可以通过<bean>标签 lazy-init 属性的实现延迟实例化对象

注意:lazy-init="false"只对 scope 属性为 singleton 才有效,如果 scope 属性为 pototype, 无论 lazy-init 的属性值是什么,都只在通过 getbean 时进行实例化

  • 立即创建:
    lazy-init=“false”(默认)
    在SpringIOC容器启动时会实例化配置文件中的所有Bean对象
  • 延迟创建
    lazy-init=“true”
    当调用getBean方法时创建对象

DI-依赖注入

  • 概念:依赖注入是指在 Spring IOC 容器创建对象的过程中,将所 依赖的对象通过配置进行注入。我们可以通过依赖注入的方式来降低对象间的耦合度。

在软件工程中,对象之间的耦合度就是对象之间的依赖性。对象之间的耦合越高,维护 成本越高,因此对象的设计应使对象之间的耦合越小越好

类的关系

继承 实现 依赖 关联 聚合 组合

依赖关系

  • 依赖关系:是一种使用的关系, 即一个类的实现需要另一个类的协助, 所以要尽量 不使用双向的互相依赖
  • 代码表现:局部变量、方法的参数或者对静态方法的调用
  • 箭头及指向:带箭头的虚线,指向被使用者

聚合

  • 聚合关系:是整体与部分的关系.如车和轮胎是整体和部分的关系. 聚合关系是关联关系的一种,是强的关联关系;关联和聚合在语法上无法区分,必须考察具体的逻辑关系。
  • 代码体现:成员变量
  • 箭头及指向:带空心菱形的实心线,菱形指向整体

关系强度

继承 = 实现 > 组合 > 聚合 > 关联 > 依赖

开闭原则

定义

OCP (Open Close Principle): 软件本身应该是可扩展的,而不可修改的。也就是,对扩 展开放,对修改封闭的

开闭原则优点

  • 易扩展。开闭原则的定义就要求对扩展开放。
  • 易维护。软件开发中,对现有代码的修改是一件很有风险的事情,符合开闭原则的设计 在扩展时无需修改现有代码,规避了这个风险,大大提交了可维护性。

高内聚、低耦合

  • 高内聚是指相关度比较高的部分尽可能的集中,不要分散。
  • 低耦合就是说两个相关的模块尽可以能把依赖的部分降低到最小,不要产生强依赖。

依赖注入的方式

在使用依赖注入时,如果注入的是 Bean 对象,那么要求注入的 Bean 对象与被注入的 Bean 对象都需要 Spring IOC 容器来实例化

通过Set方法注入

需要为注入的成员变量提供Set方法

Bean对象
private UsersDao usersDao; 
public UsersDao getUsersDao() { 
	return usersDao; 
}
public void setUsersDao(UsersDao usersDao) { 
	this.usersDao = usersDao; 
}
配置文件
<bean id="usersService" name="name1,name2,name3" class="com.lanh.service.impl.UsersServiceImpl">
 <property name="usersDao"> 
	<ref bean="usersDaoMybatis"/> 
</property> 
<!-- <property name="usersDao" ref="usersDaoMybatis"/>--> 
</bean>

通过构造方式注入

Bean对象中需要提供有参的构造方法

Bean对象
private UsersDao usersDao; 
public UsersServiceImpl(UsersDao usersDao){ 
	this.usersDao = usersDao; 
}
配置文件
<bean id="usersService" name="name1,name2,name3" class="com.lanh.service.impl.UsersServiceImpl"> 
<!-- name:根据参数名称识别参数 index:根据参数的位置来识别参数 type:根据参数的类型识别参数 -->
 <constructor-arg name="usersDao"> 
 <ref bean="usersDaoMybatis"/>
 </constructor-arg> 
 <!-- <constructor-arg name="usersDao" ref="usersDaoMybatis"/>--> 
 </bean>

自动注入

自动注入的方式有两种,一种是全局配置自动注入,另一种是局部配置自动注入。
无论全局配置或局部单独配置,都有 5 个值可以选择:

  • no:当 autowire 设置为 no 的时候,Spring 就不会进行自动注入。
  • byName:在 Spring 容器中查找 id 与属性名相同的 bean,并进行注入。需要提供 set 方 法。
  • byType:在 Spring 容器中查找类型与属性名的类型相同的 bean,并进行注入。需要提21
    供 set 方法。
    constructor:仍旧是使用 byName 方式,只不过注入的时候,使用构造方式进行注入。
    default:全局配置的 default 相当于 no,局部的 default 表示使用全局配置设置
局部自动注入

通过 bean 标签中的 autowire 属性配置自动注入。
有效范围:仅针对当前 bean 标签生效

<bean id="usersDaoMybatis" class="com.lanh.dao.impl.UsersDaoMybatisImpl"/> 
<bean id="usersService" name="name1,name2,name3" class="com.lanh.service.impl.UsersServiceImpl" autowire="byType"> </bean>
全局自动注入

通过 beans 标签中的 default-autowire 属性配置自动注入。
有效范围:配置文件中的所有 bean 标签都生效

<?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 http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName">

依赖注入的数据类型

注入Bean对象

  • 方式一
<property name="FieldName"> 
<ref bean="BeanID"/> 
</property>
  • 方式二
<property name="FieldName" ref="BeanID"/>

注入基本数据类型和字符串

  • 方式一
<property name="FieldName"> 
<value>content</value>
 </property>

-方式二

<property name="FieldName" value="Content"/>

注入List

<property name="FieldName" > 
<list> 
	<value/>或者<bean/>或者<ref/>......
</list> 
</property>

注入Set

<property name="FieldName" >
 <set>
 	<value/>或者<bean/>或者<ref/>...... 
 </set> 
 </property>

注入Map

  • 方式一
<property name="FieldName" > 
<map>
	<entry key="KeyName" value="Content"/> 
	<!-- 如果是对象 则: -->
	<!-- <entry key="KeyName" value-ref="BeanID"/> -->
</map> 
</property>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绿豆蛙给生活加点甜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值