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(一) 写了删删了写,反复几次,对自己的描述很不 ...
随机推荐
- 分布式存储系统之Ceph集群访问接口启用
前文我们使用ceph-deploy工具简单拉起了ceph底层存储集群RADOS,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/16724473.html:今天我 ...
- Go_gin权限验证
权限管理 Casbin是用于Golang项目的功能强大且高效的开源访问控制库. 1. 特征 Casbin的作用: 以经典{subject, object, action}形式或您定义的自定义形式实施策 ...
- 结构体struct知识
2022-10-12 08:52:03 // 结构体知识#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>#include<m ...
- python 运行错误收集
目录 global全局声明错误 global全局声明错误 SyntaxError: name 'is_login' is used prior to global declaration 解决办法:g ...
- 腾讯云短信SDK-精简版
/** * 腾讯云短信SDK-精简版 * 本模块使用-向腾讯云短信服务器发送请求 * @return json 腾讯服务器返回值-json字符串 */ private function send_sm ...
- vue中动态引入图片为什么要是require, 你不知道的那些事
相信用过vue的小伙伴,肯定被面试官问过这样一个问题:在vue中动态的引入图片为什么要使用require 有些小伙伴,可能会轻蔑一笑:呵,就这,因为动态添加src被当做静态资源处理了,没有进行编译,所 ...
- 【k8s连载系列】k8s介绍
k8s是Kubernetes的缩写,Google 于 2014 年开源了 Kubernetes 项目. 一.k8s的历史演变 k8s的演变过程:首先从传统的服务-->虚拟机部署-->容器部 ...
- 我服了!SpringBoot升级后这服务我一个星期都没跑起来!(上)
最近由于各方面的原因在准备升级 Spring Cloud 和 Spring Boot,经过一系列前置的调研和分析,决定把Spring Boot 相关版本从 2.1.6 升级到 2.7.5,Spring ...
- OpenMP 教程(一) 深入人剖析 OpenMP reduction 子句
OpenMP 教程(一) 深入人剖析 OpenMP reduction 子句 前言 在前面的教程OpenMP入门当中我们简要介绍了 OpenMP 的一些基础的使用方法,在本篇文章当中我们将从一些基础的 ...
- gorm
特性 全功能 ORM 关联 (Has One,Has Many,Belongs To,Many To Many,多态,单表继承) Create,Save,Update,Delete,Find 中钩子方 ...