Spring IOC 自学笔记
1、概述
Spring框架是一个开源的J2EE应用程序框架;
2、IOC和AOP
IOC:控制反转,把创建对象过程交给Spring进行管理;
Aop:面向切面,不修改源代码进行功能增强;
3、什么是IOC
-
概念:IoC是Inversion of Control的缩写,翻译成“控制反转”
-
IOC理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间的解耦。
-
软件系统在引入IOC容器之后,这种情形就完全改变了,如图3所示,由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。
-
通过前后的对比,我们不难看出来:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。
-
底层技术:
xml解析
设计模式—工厂模式
反射 -
个人理解IOC
其实IOC与面向对象一样,将创建对象的权力交给IOC管理
4、IOC如何降低耦合
5、IOC(接口)
IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
Spring提供IOC容器实现两种方式
- BeanFactory:IOC容器的基本实现,是spring内部的使用接口,不提供开发人员进行使用
- ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能
区别: - BeanFactory:加载配置文件时,不会创建对象,只有在使用时才会创建
- ApplicationContext:加载配置文件时就创建了对象
ApplicationContext实现类:(区别有哪些?)
FileSystemXmlApplicationContext :加载配置文件时,写的时系统路径(盘符)
ClassPathXmlApplicationContext:加载配置文件时,写的是类路径
ApplicationContext context = new ClassPathXmlApplicationContext(bean.xml)
6、IOC操作Bean管理
- bean管理有两个操作
spring创建对象
spring输入属性 - bean管理有两个方式
配置文件xml方式
注解方式
7、IOC基于xml操作
- 创建对象
- 配置xml,创建对象时默认使用无参的构造方法
<bean id="user" class="com.atguigu.spring5.User"></bean>
// id属性:创建唯一表示,用于创建对象找到对应的类
// class属性:则是指定对应的类路径
- DI注入,注入属性
- set方法进行注入
<bean id="book" class="com.atguigu.Book">
// property标签中,name属性的值是set方法名的值setname
<property name="name" value="红楼梦"></property>
<property name="price" value="99"></property>
</bean>
package com.atguigu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import static org.junit.Assert.*;
public class BookTest {
@Test
public void bookTest() {
ApplicationContext context =new ClassPathXmlApplicationContext("bean1.xml");
Book book = context.getBean("book",Book.class);
book.bookToString();
}
}
- 有参构造方法注入
<bean id="user" class="com.atguigu.User">
<constructor-arg name="name" value="xiaoming"></constructor-arg>
<constructor-arg name="age" value="12"></constructor-arg>
</bean>
package com.atguigu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import static org.junit.Assert.*;
public class UserTest {
@Test
public void userTest() {
ApplicationContext context =new ClassPathXmlApplicationContext("bean1.xml");
// 根据配置文件bean标签的constructor-arg 标签属性
User user = context.getBean("user",User.class);
user.userTest();
}
}
注入空值及特殊字符
- 注入空值
<bean id="book" class="com.atguigu.Book">
// property标签中,name属性的值是set方法名的值setname
<property name="name" value="红楼梦"></property>
<property name="price">
<null/>
</property>
</bean>
- 注入特殊字符
// 转义的方法
// CDATA方法
<bean id="book" class="com.atguigu.Book">
// property标签中,name属性的值是set方法名的值setname
<property name="name" value="红楼梦"></property>
<property name="price">
<value><![CDATA[<<南京>>]]></value>
</property>
</bean>
8、注入外部bean
<bean id="userservice" class="com.atguigu.service.UserService">
<property name="userDao" ref="userdaoimpl"></property>
</bean>
<bean id="userdaoimpl" class="com.atguigu.dao.Impl.UserDaoImpl">
</bean>
9、注入内部bean和级联
<!-- 级联bean注入 -->
<bean id="studentFour" class="com.atguigu.spring.pojo.Student">
<property name="sid" value="1001"></property>
<property name="sname" value="小刚"></property>
<property name="age" value="10"></property>
<property name="gender" value="男"></property>
<property name="clazz" ref="clazzOne"></property>
<property name="clazz.cId" value="2"></property>
<property name="clazz.cName" value="12班"></property>
</bean>
<bean id="clazzOne" class="com.atguigu.spring.pojo.Clazz">
<!-- <property name="cId" value="1"></property> -->
<!-- <property name="cName" value="11班"></property> -->
</bean>
<!-- 内部bean注入 -->
<bean id="studentFive" class="com.atguigu.spring.pojo.Student">
<property name="sid" value="1001"></property>
<property name="sname" value="小刚"></property>
<property name="age" value="10"></property>
<property name="gender" value="男"></property>
<property name="clazz">
<bean id="clazzInner" class="com.atguigu.spring.pojo.Clazz">
<property name="cId" value="3"></property>
<property name="cName" value="13班"></property>
</bean>
</property>
</bean>
10、注入集合类型的属性
<bean id="clazzFirst" class="com.atguigu.spring.pojo.Clazz">
<property name="cId" value="4"></property>
<property name="cName" value="集合班"></property>
<property name="students" ref="studentList"></property>
</bean>
<util:list id="studentList">
<ref bean="studentFour"></ref>
<ref bean="studentFive"></ref>
</util:list>
11、IOC操作bean管理有两种
1、普通的bean,特点:
在配置文件中class属性中定义的什么类型就返回什么类型
2、工厂bean,FactoryBean,特点:
class定义的类型和返回的类型可以不一致
- 定义一个类实现FactoryBean接口
- 实现接口内的方法,在方法中定义返回的bean类型
12、bean的作用域
1)、在spring中、设置创建bean实例默认是单实例
2)、spring中,bean标签可以通过scop属性来设置单实例还是多实例;
3)、singleton和prototype
13、bean的生命周期
- 通过构造器构造bean实例(无参构造器)
- 为bean实例的属性设置值和对其他bean的引用
- 调用后置处理器(需要实现BeanPostProcesser接口,并实现postProcessBeforeInitialization方法)
- 调用bean初始化的方法(需手动配置初始化方法)
- 调用后置处理器(需要实现BeanPostProcesser接口,并实现postProcessAfterInitialization方法)
- bean可以使用了
- 当容器关闭时,调用bean销毁的方法
14、IOC操作Bean管理(xml自动装配)
如果使用autowire="byType",则不能有俩个相同类型的bean
15、基于注解方式实现bean管理
16、基于注解创建对象
步骤:
1、引入依赖;
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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--基于注解实现bean管理,第二步:开启组件-->
<!-- 扫描指定的包,两种方式:
1、指定每个包路径,用逗号隔开;
2、指定多个包的上级目录;
-->
<context:component-scan base-package="com.atguigu.service,com.atguigu.dao"></context:component-scan>
<context:component-scan base-package="com.atguigu"></context:component-scan>
3、使用注解创建对象
package com.atguigu.service;
import org.springframework.stereotype.Component;
// 使用注解创建对象
// value属性可以不写,默认值是类的名称首字母小写
@Component(value = "bookService") // value="bookService" 等同于<bean id = "bookService" class="..">
public class BookService {
public void add(){
System.out.println("bookservice的add方法!");
}
}
17、开启组件扫描的细节
18、基于注解实现属性注入
@AutoWired:可以根据属性的类型进行注入
package com.atguigu.dao.Impl;
import com.atguigu.dao.CarDao;
import org.springframework.stereotype.Repository;
@Repository
public class CarDaoImpl implements CarDao {
public void update(){
System.out.println("car实现类!");
}
}
// service类
package com.atguigu.service;
import com.atguigu.dao.CarDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class CarService {
// 不需要有set方法
// 根据类型进行注入
@Autowired
private CarDao car;
public void test(){
System.out.println("service的方法");
car.update();
}
}
@Qualifier:可以根据属性的名称进行注入
// @Qualifer需要和@Autowired一起使用;
// 当一个接口有多个实现类时,@Autowired就不知道注入哪个类型,此时需要配合@Qualifer
//根据名称注入
package com.atguigu.dao.Impl;
import com.atguigu.dao.CarDao;
import org.springframework.stereotype.Repository;
@Repository(value = "carDaoImpl2")
public class CarDaoImpl implements CarDao {
public void update(){
System.out.println("car实现类!");
}
}
// service类
package com.atguigu.service;
import com.atguigu.dao.CarDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class CarService {
// 不需要有set方法
// 根据类型进行注入
@Autowired
// value值和实现类的value值保持一致
@Qualifier(value = "carDaoImpl2")
private CarDao car;
public void test(){
System.out.println("service的方法");
car.update();
}
}
@Resource:可以根据属性的类型或者属性的名称进行注入
@Value:普通类型属性的注入
19、完全注解开发
1、创建配置类,替换xml配置文件
package com.atguigu.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
// 添加注解,使得此类被spring识别为“配置类”;
@Configuration
// 使用注解开启注解扫描
@ComponentScan(basePackages = {"com.atguigu"})
public class SpringConfig {
}
2、修改测试方法
@Test
public void test2() {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
CarService carService = context.getBean("carService",CarService.class);
carService.test();
}
20、DI和IOC
1、IOC是思想,DI是实现方式。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了