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(一) 写了删删了写,反复几次,对自己的描述很不 ...
随机推荐
- LeetCode - 数组遍历
1. 485. 最大连续 1 的个数 1.1 分析题意 首先:我们求的是连续的1的个数,所以我们不能也没必要对数组进行排序: 其次:只要求求出最大连续1的个数,并不要求具体的区间数目,所以我们只需要用 ...
- sql 中HAVING函数
select * from <表名> group by<过滤的数据> having <晒选的列名>=<条件> 例 select * from villa ...
- zookeeper之安装
zookeeper之安装 一.准备条件 1.1 最低三个服务器(一主多从,1个leader,多个flower)1.2 将zookeeper安装包上传到集群并解压zookeeper 二.将conf目录下 ...
- CQOI2015任务查询系统
题目链接 主席树. 把区间的影响挂在左端点与右端点,建树时顺便对应的插入与删除. 维护一段值域区间的和与数字个数,查询时要注意与第k大的数相同的数可能有很多. 复杂度O(nlogn) #include ...
- sql语法巧用之not取反
数据库的重要性和通用性都不用说了,什么sql的通用性,sql优化之类的也不必说了,咱们今天来聊聊另一个有意思的话题:如何取一个筛选的反面案例. 1. 举几个正反案例的例子 为了让大家理解我们的假设场景 ...
- IDEA中Java项目创建lib目录并生成依赖
首先介绍说明一下idea在创建普通的Java项目,是没有lib文件夹的,下面我来带大家来创建一下1.右键点击项目,创建一个普通的文件夹 2.取名为lib 3.把项目所需的jar包复制到lib文件夹下 ...
- 记录redis集群连接超时问题及解决方案
下午同事反馈,某业务场景性能测试过程中,出现异常,提供日志报: Redis command timed out 1. 先看下日志 org.springframework.dao.QueryTimeou ...
- 2021-2022 ICPC, NERC, Northern Eurasia Onsite (Unrated, Online Mirror, ICPC Rules, Teams Preferred) J. Job Lookup
题意 n个节点,n<=200,你需要构造这n个几点成为一棵树,并且这棵树的中序遍历为1-n; 你构造树的节点之间的最短路构成一个n×n的最短距离矩阵d: 同时给你n×n的权重矩阵c:最最小的Σd ...
- Seata Server 1.5.2 源码学习
Seata 包括 Server端和Client端.Seata中有三种角色:TC.TM.RM,其中,Server端就是TC,TM和RM属Client端.Client端的源码学习上一篇已讲过,详见 < ...
- 【云原生 · Kubernetes】apiserver高可用
个人名片: 因为云计算成为了监控工程师 个人博客:念舒_C.ying CSDN主页️:念舒_C.ying 7.1 高可用选型 ipvs+keepalived nginx+keepalived hap ...