Spring IOC 复习
Inversion of Control
将创建对象的权利交给框架,包括DI(Dependency Injection,依赖注入)和DL(Dependency Lookup,依赖查找),能削减计算机程序的耦合,即解除代码中的依赖关系
应用
xml
建立maven工程
导入jar包,pom.xml中加入spring-context依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
创建配置文件,在resources目录下新建bean.xml文件,并导入约束
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
配置bean,在bean.xml中的beans标签中加入bean标签配置bean
- 使用默认构造函数,如果类中无默认构造函数则无法创建
<bean id="bean的唯一标识(名字)" class="全限定类名"></bean>
- 使用某个类(工厂)的某个方法创建对象
<bean id="beanId" factory-bean="工厂类的全限定类名" factory-method="方法名"></bean>
- 使用某个类(静态工厂)的某个静态方法创建对象
<bean id="beanId" class="全限定类名" factory-method="方法名"></bean>
bean标签还有两个属性init-method和destroy-method指定构造方法和销毁方法
依赖注入
在bean中需要的数据或其他类的对象都由spring提供,只需配置,但不适合注入常变的数据
能注入的数据有三类:基本类型和String,其他bean,复杂类型/集合类型
注入方式有三种,在bean标签内用一个标签代表一个参数:
构造函数注入
<constructor-arg type(不常)="类型的全限定名" index(不常)="参数序号,从0开始" name(常用)="参数名" value="基本类型值" ref="引用其他bean"></constructor-arg>
优:获取bean对象时注入数据是必须的,否则无法创建成功
弊:改变了bean的实例化方式,在创建对象时如果用不到这些数据也必须提供
set方法注入(常用)
<property name="set方法对应名" value="基本类型值" ref="其他bean"></property>
优:创建对象时没有明确的限制,可以直接使用默认构造函数
弊:set方法可能不执行,如果某个成员必须有值,此方法不能保证
复杂类型的注入需要在参数标签中再加标签array,list,set,map,props
<property name="listPropName">
<array>
<value>...</value>
...
</array>
</property>
<property name="mapPropName">
<map>
<entry key="keyName" value="值"></entry>
<entry key="keyName">
<value>值</value>
</entry>
</map>
</property>
List结构的用list,array,set都一样,Map结构的用map,props都一样
获取bean,在java代码中
//获取核心容器对象,也可以用BeanFactory代替ApplicationContext
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//根据id获取Bean对象
ClassOfBean bean = (ClassOfBean)ac.getBean("beanId");
- ApplicationContext的三个常用实现类
ClassPathXmlApplicationContext: 可以加载类路径下的配置文件
FileSystemXmlApplicationContext: 可以加载磁盘任意路径(有访问权限)下的配置文件
AnnotationConfigApplicationContext: 用于读取注解创建容器
- ApplicationContext和BeanFactory的区别
前者在构建容器时采用立即加载的方式,一读取完配置文件就马上创建bean
后者在构建窗口时采用延迟加载的方式,当获取bean时才真正创建对象
注解
用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"
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">
<!-- 告知spring在创建容器时要扫描的包 -->
<context:component-scan base-package="包路径"></context:component-scan>
</beans>
不用xml文件
创建一个配置类,类上加
@Configuration指定当前类是一个配置类,获取容器时作为参数传入的配置类可以不加
@ComponentScan(basePackages="包路径")指定要扫描的包,basePackages可以换成value
获取容器时用new AnnotationConfigApplicationContext(配置类.class)
@Import 导入其他配置类,被导入的类不用再加@Configuration
@PropertySource("classpath:路径/文件名") 用指定properties文件的位置,属性value
@PropertySources 有多个properties文件的时候用
导入配置文件后可以用@Value(${...})读取
与bean有关的注解
@Bean 用于将当前方法的返回值作为bean存入ioc容器中,属性name指定beanId默认值为当前方法的名称,如果方法有参数,spring框架会去容器中查找 有没有可用的bean对象,查找方式同Autowired
用于创建对象的,相当于bean标签
@Component 作用:把当前对象存入spring容器中;属性:value:指定bean的id,默认是当前类名且首字母小写;@Controller @Service @Repository与@Component完全一样,体现三层架构
用于注入数据的,相当于property标签
@Autowired 作用:自动按照类型注入,如果容器中有唯一一个类匹配该数据的类型则注入,若没有匹配类型则报错,如果有多个则通过变量名寻找beanId对应的那个bean注入;位置:类上,方法上,变量上
@Qualifier 作用:在按照类型注入的基础上再按照名称注入,在给类成员注入时不能单独使用必须和@Autowired一起,但在给方法参数注入时可以;属性:value用于指定beanId
以上三种只能注入bean,不基本类型和String,复杂类型必须用xml配置
@Value 作用:用于注入基本类型和String;属性:value用于指定数据的值,可以使用SpEL(spring的EL表达式:${表达式})
@Resource 作用:直接按照bean的id注入,可以独立使用;属性:name指定beanId
用于改变作用范围的,相当于bean标签的scope属性
@Scope 作用:指定bean的作用范围;属性:value一般取singleton(默认)或prototype
和生命周期相关的,相当于bean标签的init-method和destroy-method属性(不常用)
@PostConstruct
@PreDestroy
与Junit整合
添加spring-test和junit依赖,spring5.x要求junit 4.12及以上
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
使用Junit提供的一个注解@RunWith把原有的main方法替换成spring提供的
@RunWith(SpringJUnit4ClassRunner.class)
告知spring的运行器,是基于xml还是注解,并说明位置
@ContextConfiguration
locations: 指定xml文件位置
classes: 指定注解类所在位置
常见问题
bean的作用范围
bean标签和@Component注解的scope属性:用于指定bean的作用范围
取值:singleton 单例的(常用)
prototype 多例的(常用)
request 作用于web应用的请求范围
session 作用于web应用的会话范围
global-session 集群环境的会话范围(全局会话范围),若不是集群环境,则为session
bean的生命周期
singleton: 容器创建时对象创建(ApplicationContext),容器销毁时对象销毁
prototype: 使用对象时创建对象,当对象长时间不用且长时间没有别的对象引用时,由java的垃圾回收器回收
原理
ioc只需要导入spring-context依赖
阅读源码:github下载源码,导入idea,运行调试加注释
spring项目启动后,会扫描所有类,找到符合bean标准(加注释或xml配置)的类,通过一个描述类(BeanDefinition)存放bean的信息,isSingleton属性默认为true,再将描述类存入一个map(BeanDefinationMap)中
扫描之后bean的获取:通过BeanDefinationMap里的key(bean名)找到value(BeanDefination)的class属性进行反射,找到bean对应的类。与class名没有关系,可以通过自己实现BeanFactory接口,从beanFactory中获取描述类BeanDefinition,setBeanClass(another.class)将bean和class的对应关系更改
扫描前BeanDefinationMap中已有7个bean,包括AppConfig
main() --> AnnotationConfigApplicationContext(AppConfig.class) --> refresh() --> invokeBeanFactoryPostProcessors(beanFactory)(扫描并存入bean)
后置处理器BeanPostProcessors的子类会被自动扫描并对bean进行多层代理,默认有九次(进入依赖注入等操作),实现此接口可以对bean的创建过程进行干预
Spring上下文或环境:为了实现IOC或AOP所需要的各种Spring组件的集合,如BeanDefination,BeanPostProcessor(后置处理器),DefaultListableBeanFactory,BeanDefinitionMap,单例池等等
扫描只是将bean对应的类的信息存入map中,并不会实例化类,即lazy(懒加载)
factoryBean是一个特殊的bean,beanFactory是bean工厂
单例bean第一次被实例化后就会存入名为singleObjects的map(单例池)中,再次getBean()时就不会new,(保证单例)
Spring容器:不止单例池,还包括其他IOC组件
循环依赖:
单例bean的循环依赖
isSingletonCurrentlyInCreation判断这个bean是否在创建过程中
单例池只存放完整的bean
get(A) --> new A --> auto B --> get(B) --> new B --> auto A --> get(A)
获取A,新建A,发现A需要注入B且单例池中没有B且B不在创建过程中,获取B,发现B需要注入A且单例池中没有A且A正在创建过程中,获取A并注入B,将B注入A,将A放入单例池
Spring IOC 复习的更多相关文章
- [Java复习] Spring IoC
1. Spring bean的生命周期? 1. 对Bean进行实例化(相当于new) 对于BeanFactory 当客户向容器请求一个尚未初始化的bean(或初始化bean需要注入另外一个尚未初始化的 ...
- 一篇关于spring ioc 依赖注入3种方式的文章引用
今天看到一篇spring ioc 容器依赖注入3种方式的文章,为了方便后面的复习,在此引用别人的文章,查看请戳我.
- Spring知识点复习
Spring知识点复习 一.专业术语 侵入式设计 引入框架,对现有的类的结构有影响,即需要实现或继承某些特定类.如:Struts框架 非侵入式设计 引入框架,对现有的类结构没有影响.如:Hiberna ...
- Spring IOC(一)
最近复习,准备整理下复习笔记 Spring IOC 部分: 控制反转(Inversion of Control) IOC是什么 简言之 IOC完成的事情原先由程序员主动通过new实例化对象事情,转交给 ...
- 应聘阿里,字节跳动,美团必须掌握的Spring IOC与工厂模式
Spring IOC与工厂模式 PS:本文内容较为硬核,需要对java的面向对象.反射.类加载器.泛型.properties.XML等基础知识有较深理解. (一)简单介绍 在讲Spring IOC之前 ...
- Spring IoC总结
Spring 复习 1.Spring IoC 1.1 基本概念 1.1.1 DIP(Dependency Inversion Principle) 字面意思依赖反转原则,即调用某个类的构造器创建对象时 ...
- Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析
Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析 前言 上一篇文章Spring Ioc源码分析系列--Ioc源码入口分析已经介绍到Ioc容器 ...
- 【初探Spring】------Spring IOC(三):初始化过程---Resource定位
我们知道Spring的IoC起到了一个容器的作用,其中装得都是各种各样的Bean.同时在我们刚刚开始学习Spring的时候都是通过xml文件来定义Bean,Spring会某种方式加载这些xml文件,然 ...
- 【初探Spring】------Spring IOC(一)
IOC:Inversion of Control(控制反转).IOC它所体现的并不是一种技术,而是一种思想,一种将设计好的对象交给容器来管理的思想.IOC的核心思想就体现在控制.反转这两个词上面,要理 ...
随机推荐
- JS高阶---函数的prototype
思维导图 栈堆翻译为为stack (1)原型与原型链 概念一.原型对象 验证步骤: 1.打印Data函数的原型prototype 原型属性指向原型对象 ===ES源码结构分析示意=== 2.空对象 3 ...
- Linux下JDK中文字体乱码
java生成图片的时候用到字体,但是liunx系统没有这些字体需要把C:\Windows\Fonts 上传到/usr/local/jdk1.8.0_171/jre/lib/fonts 重启tomcat ...
- JavaEE 项目部署方式
一.手动部署 二.自动部署 “自动化”的具体体现:向版本库提交新的代码后,应用服务器上自动部署,用户或测试人员使用的马上就是最新的应用程序. 搭建上述持续集成环境可以把整个构建.部署过程自动化,很大程 ...
- zz阿里小蜜—智能服务技术实践及场景探索(AI先行者大会)Final.pdf
SLQA+ 模型
- 成神之Java之路
既然励志在java路上走的更远,那就必须了解java的路径.先看图 image.png 更加细化的细节如下 一: 编程基础 不管是C还是C++,不管是Java还是PHP,想成为一名合格的程序员,基本的 ...
- bcc 基于bpf 分析linux 系统性能的强大工具包
bcc 是一个基于bpf 的强大linux io,网络监控分析工具集(当然也可以分析java,ruby,python...) 一张工具图 说明 bcc 好多工具是需要kernel 4.1 的,但是大部 ...
- 【CF1097F】Alex and a TV Show
[CF1097F]Alex and a TV Show 题面 洛谷 题解 我们对于某个集合中的每个\(i\),令\(f(i)\)表示\(i\)作为约数出现次数的奇偶性. 因为只要因为奇偶性只有\(0, ...
- [LeetCode] 344. Reverse String 翻转字符串
Write a function that reverses a string. The input string is given as an array of characters char[]. ...
- 主流chatbot机器人调研
wit.ai api.ai microsoft bot frameword rasa pydial 问答系统 语义匹配 语义表示式匹配与交互式匹配.语义表示式匹配是将用户query与候选query分别 ...
- Golang(十二)TLS 相关知识(三)理解并模拟简单代理
0. 前言 前面的介绍我们理解了数字签名等知识,同时学习了 OpenSSL 生成私钥和证书并验证 之前提过我们基于 BitTorrent 协议开发了一个 docker 镜像分发加速插件 中间涉及到了配 ...