Spring IOC官方文档学习笔记(二)之Bean概述
1.Bean概述
(1) Spring IoC容器管理一个或多个bean,这些bean是根据我们所提供的配置元数据来创建的,在容器内部,BeanDefinition对象就代表了bean的配置元数据,它主要包含了如下几个方面的内容:
| 属性 | 说明 |
|---|---|
| Class | 全限定类名 |
| Name | bean的名称 |
| Scope | bean的作用域 |
| Constructor arguments | 构造函数参数 |
| Properties | 成员变量属性值 |
| Autowiring Mode | 自动装配模式 |
| Lazy initialization mode | 懒加载模式 |
| Initialization Method | 初始化回调 |
| Destruction Method | 销毁回调 |
(2) 一般情况下,Spring中的bean来自于Spring的自动扫描解析,除此之外,Spring还允许我们手动的向容器中注册一些额外的对象,如下所示:
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("boke/definition.xml");
//1.获取ApplicationContext中的BeanFactory
ConfigurableListableBeanFactory beanFactory = ctx.getBeanFactory();
Man man = new Man();
//2.通过beanFactory的registerSingleton方法向容器中注册容器外的额外对象
beanFactory.registerSingleton("man", man);
//3.注册之后,便可获取使用该对象
Man existMan = beanFactory.getBean("man", Man.class);
existMan.doSomething();
总结一下,向Spring IOC容器中注册额外对象,大致可分为两步:
第一步:通过调用ApplicationContext实现类们的getBeanFactory()方法拿到DefaultListableBeanFactory
第二步:调用DefaultListableBeanFactory中的registerSingleton()方法或registerBeanDefinition()来向容器中注册额外对象
注意:在实践上由我们手动注册的bean需要尽早向容器中注册,如果注册的太晚,就无法和Spring所提供的一些步骤结合,会导致一些依赖注入失败
2.命名Bean
(1) Spring中的bean通常有一个唯一的id和多个别名,在基于xml的配置中,可通过bean标签中的id属性和name属性来标识一个bean的id和别名,其中id属性必须唯一,而name属性可不唯一,多个别名之间用分号,逗号或空格分隔开,如下所示:
<!-- xml文件内容 -->
<beans ...>
<!-- 定义了一个bean,它的id为man,别名为thisMan,yesMan -->
<bean class="cn.example.spring.boke.Man" id="man" name="thisMan,yesMan"> </bean>
</beans>
//Java代码:
ApplicationContext ctx = new ClassPathXmlApplicationContext("boke/from.xml");
//打印下面这三个Man对象的地址,发现它们的地址相同,为同一对象
Man man = (Man) ctx.getBean("man"), thisMan = (Man) ctx.getBean("thisMan"), yesMan = (Man) ctx.getBean("yesMan");
(2) 在基于Java code的配置中,如使用@Bean,@Component等注解时,id或name属性不是必须提供的,如果都没有,Spring容器会默认提供一个唯一的id(生成规则:通常情况下会按照驼峰命名法取类名并将其首字母小写,但如果类名的第一,二个字符都是大写时,会保留原始大小写),如下所示
//例子一:定义一个bean,未声明它的id或name,此时Spring会自动帮我们生成一个唯一的id,为exampleA
@Component
public class ExampleA {
public void doSomething() {
System.out.println("Hello This is ExampleA");
}
}
//从Spring IOC中获取上面这个bean
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext("cn.example.spring");
//使用exampleA这个id来寻找容器中ExampleA对象
ExampleA exampleA = (ExampleA) ctx.getBean("exampleA");
exampleA.doSomething();
//例子二:定义了一个bean,未声明它的id或name,且该类名的第一,二个字符都是大写,此时Spring为其生成的id为IMyService,与类名相同
@Component
public class IMyService {
}
//验证过程省略...
(3) 还可以使用alias标签来定义一个bean的别名,如下
<beans ...>
<bean class="cn.example.spring.boke.ExampleA" id="exampleA"> </bean>
<!-- 此时,既可以用exampleA来获取到这个bean,也可以用aliasA来获取这个bean,它俩是等价的 -->
<alias name="exampleA" alias="aliasA"></alias>
</beans>
3.实例化bean
(1) BeanDefinition在本质上就是bean的‘配方表’,容器会根据BeanDefinition中的配置信息来创建出所需要的对象供我们使用,在基于xml的配置中,通过bean标签中的class属性来指定要创建对象的类类型,这个bean标签中的class属性对应于BeanDefanition里的Class属性
(2) 通过美元符号($)或点符号(.)来注册静态内部类,如下
public class Outer {
//注意:这里是‘静态‘内部类
public static class Inner {
public void doSomething() {
System.out.println("Here is inner");
}
}
}
<!-- xml文件配置 -->
<beans ...>
<!-- 使用$调用静态内部类 -->
<bean class="cn.example.spring.boke.Outer$Inner" id="inner"></bean>
<!-- 使用.调用静态内部类,与上面的等价 -->
<!-- <bean class="cn.example.spring.boke.Outer.Inner" id="inner"></bean> -->
</beans>
//使用
ApplicationContext ctx = new ClassPathXmlApplicationContext("boke/from.xml");
//获取已注册到容器中的静态内部类
Outer.Inner inner = (Outer.Inner) ctx.getBean("inner");
inner.doSomething();
(3) 实例化bean的方式
- 通过构造函数:最常用的方式,无需实现任何特定的接口,只需简单的指定bean的class属性即可,如下所示
<beans ...>
<!-- 此时,Spring会调用无参构造函数来实例化ExampleA对象,因此,请确保ExampleA中有一个无参构造器,否则,Spring会提示报错 -->
<!-- 除了默认的无参构造器外,还可指定某个有参构造器来实例化对象,见后文 -->
<bean id="exxampleA" class="cn.example.spring.boke.ExampleA"></bean>
</beans>
- 通过静态工厂方法:适用于初始化过程比较复杂的对象
//静态工厂
public class ExampleAFactory {
private static ExampleA exampleA = new ExampleA();
//注意:这里必须是'静态'工厂方法
public static ExampleA createInstance() {
return exampleA;
}
}
<!-- xml文件配置 -->
<beans ...>
<!-- class属性指定工厂类,factory-method属性指定它的静态工厂方法,Spring会调用这个工厂方法来创建并注册所需的对象 -->
<bean id="exampleA" class="cn.example.spring.boke.ExampleAFactory" factory-method="createInstance"></bean>
</beans>
//使用,与普通的bean没什么不同
ApplicationContext ctx = new ClassPathXmlApplicationContext("boke/from.xml");
ExampleA exampleA = (ExampleA)ctx.getBean("exampleA");
- 通过实例工厂方法:与静态工厂类似,不过要先注册一个实例工厂bean
//实例工厂
public class ExampleAFactory {
private static ExampleA exampleA = new ExampleA();
//这里是实例方法,注意与上面的静态工厂方法区分
public ExampleA createInstance() {
return exampleA;
}
}
<!-- xml文件配置 -->
<beans ...>
<!-- 1.首先要注册一个实例工厂bean -->
<bean id="factory" class="cn.example.spring.boke.ExampleAFactory"></bean>
<!-- 2.factory-bean指定上面这个实例工厂bean,factory-method指定它的实例方法,之后Spring会调用这个实例方法来创建并注册所需的对象 -->
<bean id="exampleA" factory-bean="factory" factory-method="createInstance"></bean>
</beans>
//此时容器有两个bean,一个是实例工厂,一个实例工厂所生产的对象
ApplicationContext ctx = new ClassPathXmlApplicationContext("boke/from.xml");
//工厂
ExampleAFactory factory = (ExampleAFactory)ctx.getBean("factory");
ExampleA exampleA = (ExampleA)ctx.getBean("exampleA");
4.确定bean的类型
(1) 通过执行调用BeanFactory.getType方法,来获取到某个特定bean的类型,如下
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("boke/from.xml");
Class clazz = ctx.getBeanFactory().getType("exampleA");
Spring IOC官方文档学习笔记(二)之Bean概述的更多相关文章
- Spring Framework 官方文档学习(二)之IoC容器与bean lifecycle
到目前为止,已经看了一百页.再次感慨下,如果想使用Spring,那可以看视频或者找例子,但如果想深入理解Spring,最好还是看官方文档. 原计划是把一些基本接口的功能.层次以及彼此的关系罗列一下.同 ...
- Spring Boot 官方文档学习(二)特点
一.SpringApplication banner,就是启动时输出的信息,可以在classpath下添加 banner.txt,或者设置 banner.location 来指向特定的文件.(默认编码 ...
- Vue.js官方文档学习笔记(二)组件化应用的构建
组件化应用的构建 组件化应用允许我们使用小型.独立和通常可复用的组件构建大型应用. Vue注册组件 Vue.component('todo-item',{template:'<li>这是个 ...
- Spring 4 官方文档学习(十二)View技术
关键词:view technology.template.template engine.markup.内容较多,按需查用即可. 介绍 Thymeleaf Groovy Markup Template ...
- Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion(二)
接前一篇 Spring Framework 官方文档学习(四)之Validation.Data Binding.Type Conversion(一) 本篇主要内容:Spring Type Conver ...
- Spring 4 官方文档学习(十一)Web MVC 框架
介绍Spring Web MVC 框架 Spring Web MVC的特性 其他MVC实现的可插拔性 DispatcherServlet 在WebApplicationContext中的特殊的bean ...
- Spring Boot 官方文档学习(一)入门及使用
个人说明:本文内容都是从为知笔记上复制过来的,样式难免走样,以后再修改吧.另外,本文可以看作官方文档的选择性的翻译(大部分),以及个人使用经验及问题. 其他说明:如果对Spring Boot没有概念, ...
- Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion(一)
题外话:本篇是对之前那篇的重排版.并拆分成两篇,免得没了看的兴趣. 前言 在Spring Framework官方文档中,这三者是放到一起讲的,但没有解释为什么放到一起.大概是默认了读者都是有相关经验的 ...
- Spring boot官方文档学习(一)
个人说明:本文内容都是从为知笔记上复制过来的,样式难免走样,以后再修改吧.另外,本文可以看作官方文档的选择性的翻译(大部分),以及个人使用经验及问题. 其他说明:如果对Spring Boot没有概念, ...
- Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion
本篇太乱,请移步: Spring Framework 官方文档学习(四)之Validation.Data Binding.Type Conversion(一) 写了删删了写,反复几次,对自己的描述很不 ...
随机推荐
- 2022.9.17 Java第二次课总结
以下是本节课后的问题 首先是关于静态变量 在类中,使用 static 修饰符修饰的属性(成员变量)称为静态变量,也可以称为类变量,常量称为静态常量,方法称为静态方法或类方法,它们统称为静态成员,归整个 ...
- uoj220【NOI2016】网格
刚了几个小时啊,这tm要是noi我怕不是直接滚粗了.我判答案为1的情况试了几种做法,最后终于想到了一个靠谱的做法,然后细节巨多,调了好久,刚拿到97分时代码有6.2KB了,后来发现有些东西好像没啥用就 ...
- winscp报错Server sent passive reply with unroutable address. Using server address instead
找了一堆没用. 最后终于 1.使用winSCP连接ftp时,编辑会话,单击高级. 2.进入高级设置之后,单击连接,查看连接模式,把被动模式的勾,勾掉. 3.单击确定,然后保存配置,重新连接FTP,OK
- Python学习笔记----列表、元组和字典的基础操作
文章目录 一.列表的基本操作 1.1 修改列表中的某个数据 1.2 获取某个元素的返回值(返回的是索引) 1.3 在列表中插入新的元素 1.4 删除列表中的元素 1.5 +和* 二.内置的函数和方法 ...
- 完全背包问题 —— 贪心优化 DP 范围
题意: 现在有 \(2n+1\) 个物品(\(n\le 300\)),体积分别为 \(-n,-n+1,\dots,-1,0,1,\dots,n\),第 \(i\) 个物品有 \(a_i\) 个,求选出 ...
- 十三、Pod的资源控制器类型
Pod 的资源控制器类型 一.Pod 的资源控制器类型 什么是控制器呢?简单来说,控制器就好比是影视剧里面的剧本,演员会根据剧本所写的内容来针对不同的角色进行演绎,而我们的控制器就好比是剧本,Kube ...
- 精简docker的导出镜像
Docker 镜像是由多个文件系统(只读层)叠加而成,每个层仅包含了前一层的差异部分.当我们启动一个容器的时候,Docker 会加载镜像层并在其上添加一个可写层.容器上所做的任何更改,譬如新建文件.更 ...
- 有用的内置Node.js APIs
前言 在构建你的第一个Node.js应用程序时,了解node开箱即用的实用工具和API是很有帮助的,可以帮助解决常见的用例和开发需求. 有用的Node.js APIs Process:检索有关环境变量 ...
- Unity坐标系入门
一.坐标系的概念 Unity 世界坐标系采用左手坐标系,大拇指指向X轴(红色),食指指向Y轴(黄色),中指向手心方向歪曲90度表示Z轴(蓝色),同时Z轴也是物体前进方向,下图表示Unity的四种坐标系 ...
- SpringCloud(九) - Nginx
1.安装Nginx 1.1 解压上传安装包 解压# nginx-1.16.1.tar.gz # nginx需要一些环境(全部执行,不存在的会执行,存在的会跳过) yum install -y wget ...