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概述的更多相关文章

  1. Spring Framework 官方文档学习(二)之IoC容器与bean lifecycle

    到目前为止,已经看了一百页.再次感慨下,如果想使用Spring,那可以看视频或者找例子,但如果想深入理解Spring,最好还是看官方文档. 原计划是把一些基本接口的功能.层次以及彼此的关系罗列一下.同 ...

  2. Spring Boot 官方文档学习(二)特点

    一.SpringApplication banner,就是启动时输出的信息,可以在classpath下添加 banner.txt,或者设置 banner.location 来指向特定的文件.(默认编码 ...

  3. Vue.js官方文档学习笔记(二)组件化应用的构建

    组件化应用的构建 组件化应用允许我们使用小型.独立和通常可复用的组件构建大型应用. Vue注册组件 Vue.component('todo-item',{template:'<li>这是个 ...

  4. Spring 4 官方文档学习(十二)View技术

    关键词:view technology.template.template engine.markup.内容较多,按需查用即可. 介绍 Thymeleaf Groovy Markup Template ...

  5. Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion(二)

    接前一篇 Spring Framework 官方文档学习(四)之Validation.Data Binding.Type Conversion(一) 本篇主要内容:Spring Type Conver ...

  6. Spring 4 官方文档学习(十一)Web MVC 框架

    介绍Spring Web MVC 框架 Spring Web MVC的特性 其他MVC实现的可插拔性 DispatcherServlet 在WebApplicationContext中的特殊的bean ...

  7. Spring Boot 官方文档学习(一)入门及使用

    个人说明:本文内容都是从为知笔记上复制过来的,样式难免走样,以后再修改吧.另外,本文可以看作官方文档的选择性的翻译(大部分),以及个人使用经验及问题. 其他说明:如果对Spring Boot没有概念, ...

  8. Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion(一)

    题外话:本篇是对之前那篇的重排版.并拆分成两篇,免得没了看的兴趣. 前言 在Spring Framework官方文档中,这三者是放到一起讲的,但没有解释为什么放到一起.大概是默认了读者都是有相关经验的 ...

  9. Spring boot官方文档学习(一)

    个人说明:本文内容都是从为知笔记上复制过来的,样式难免走样,以后再修改吧.另外,本文可以看作官方文档的选择性的翻译(大部分),以及个人使用经验及问题. 其他说明:如果对Spring Boot没有概念, ...

  10. Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion

    本篇太乱,请移步: Spring Framework 官方文档学习(四)之Validation.Data Binding.Type Conversion(一) 写了删删了写,反复几次,对自己的描述很不 ...

随机推荐

  1. PAT (Basic Level) Practice 1007 素数对猜想 分数 20

    让我们定义dn​为:dn​=pn+1​−pn​,其中pi​是第i个素数.显然有d1​=1,且对于n>1有dn​是偶数."素数对猜想"认为"存在无穷多对相邻且差为2的 ...

  2. 【前端必会】tapable、hook,webpack的灵魂

    背景 什么是tapable.hook,平时做vue开发时的webpack 配置一直都没弄懂,你也有这种情况吗? 还是看源码,闲来无聊又看一下webpack的源码,看看能否找到一些宝藏 tapable和 ...

  3. NOIP 2013 提高组 洛谷P1967 货车运输 (Kruskal重构树)

    题目: A 国有 nn 座城市,编号从 11 到 nn,城市之间有 mm 条双向道路.每一条道路对车辆都有重量限制,简称限重. 现在有 qq 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情 ...

  4. CentOS6/7开机启动配置

    最近在配置Linux系统的ntp校时,涉及到开机启动问题,总结一下 两个环境: CentOS release 6.5 (Final) CentOS Linux release 7.9.2009 (Co ...

  5. Oracle 同义词详解(synonym)

    Oracle 同义词详解(synonym) 一.Oracle同义词概念 Oracle 数据库中提供了同义词管理的功能.同义词是数据库方案对象的一个别名,经常用于简化对象访问和提高对象访问的安全性.在使 ...

  6. LOJ2325「清华集训 2017」小Y和恐怖的奴隶主

    题目链接 首先dp很显然,\(f(i,s)\)表示到了第i轮,各种血量人数的情况为s今后的期望攻击boss次数.那么有\(f(i,s)=\frac{1}{num+1}*\sum_{s->s'}( ...

  7. react.js+easyui 做一个简单的商品表

    效果图:     import React from 'react'; import { Form, FormField, Layout,DataList,LayoutPanel,Panel, Lab ...

  8. 微信小程序——悬浮按钮

    关键:    position: fixed; wxml: <navigator url="/pages/issue/index"><image class='i ...

  9. JS数据结构与算法-队列结构

    队列结构 一.认识队列 受限的线性结构: 我们已经学习了一种受限的线性结构:栈结构. 并且已经知道这种受限的数据结构对于解决某些特定问题,会有特别的 效果. 下面,我们再来学习另外一个受限的数据结构: ...

  10. 【深入浅出 Yarn 架构与实现】2-2 Yarn 基础库 - 底层通信库 RPC

    RPC(Remote Procedure Call) 是 Hadoop 服务通信的关键库,支撑上层分布式环境下复杂的进程间(Inter-Process Communication, IPC)通信逻辑, ...