Spring教程笔记(3)
getBean()
ApplicationContext接口获取Bean方法简介:
• Object getBean(String name) 根据名称返回一个Bean,客户端需要自己进行类型转换;
• T getBean(String name, Class<T> requiredType) 根据名称和指定的类型返回一个Bean,客户端无需自己进行类型转换,如果类型转换失败,容器抛出异常;
• T getBean(Class<T> requiredType) 根据指定的类型返回一个Bean,客户端无需自己进行类型转换,如果没有或有多于一个Bean存在容器将抛出异常;
• Map<String, T> getBeansOfType(Class<T> type) 根据指定的类型返回一个键值为名字和值为Bean对象的 Map,如果没有Bean对象存在则返回空的Map。
IOC容器:
IoC容器就是具有依赖注入功能的容器,IoC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。应用程序无需直接在代码中new相关的对象,应用程序由IoC容器进行组装。在Spring中BeanFactory是IoC容器的实际代表者。
Spring IoC容器如何知道哪些是它管理的对象呢?这就需要配置文件,Spring IoC容器通过读取配置文件中的配置元数据,通过元数据对应用中的各个对象进行实例化及装配。一般使用基于xml配置文件进行配置元数据,而且Spring与配置文件完全解耦的,可以使用其他任何可能的方式进行配置元数据,比如注解、基于java文件的、基于属性文件的配置都可以。
Bean:
由IoC容器管理的那些组成你应用程序的对象我们就叫它Bean, Bean就是由Spring容器初始化、装配及管理的对象,除此之外,bean就与应用程序中的其他对象没有什么区别了。那IoC怎样确定如何实例化Bean、管理Bean之间的依赖关系以及管理Bean呢?这就需要配置元数据,在Spring中由BeanDefinition代表,后边会详细介绍,配置元数据指定如何实例化Bean、如何组装Bean等。
如何工作:
一、准备配置文件:xml 就像前边Hello World配置文件一样,在配置文件中声明Bean定义也就是为Bean配置元数据。
二、由IoC容器进行解析元数据: IoC容器的Bean Reader读取并解析配置文件,根据定义生成BeanDefinition配置元数据对象,IoC容器根据BeanDefinition进行实例化、配置及组装Bean。
三、实例化IoC容器:由客户端实例化容器,并从实例容器中获得获取需要的Bean。

一般项目结构:“src”用于存放java文件;“lib”用于存放jar文件;“resources”用于存放配置文件;
public class HelloTest {
@Test //jUnit
public void testHelloWorld() {
//1、读取配置文件实例化一个IoC容器
ApplicationContext context = new ClassPathXmlApplicationContext("helloworld.xml");
//2、从容器中获取Bean,注意此处完全“面向接口编程,而不是面向实现”,hello是bean id
HelloApi helloApi = context.getBean("hello", HelloApi.class);
//3、执行业务逻辑
helloApi.sayHello();
}
}
在Spring Ioc容器的代表就是org.springframework.beans包中的BeanFactory接口,BeanFactory接口提供了IoC容器最基本功能;而org.springframework.context包下的ApplicationContext接口扩展了BeanFactory,还提供了与Spring AOP集成、国际化处理、事件传播及提供不同层次的context实现 (如针对web应用的WebApplicationContext)。简单说, BeanFactory提供了IoC容器最基本功能,而 ApplicationContext 则增加了更多支持企业级功能支持。
容器实现一览:
• XmlBeanFactory:BeanFactory实现,提供基本的IoC容器功能,可以从classpath或文件系统等获取资源;
(1) File file = new File("fileSystemConfig.xml");
Resource resource = new FileSystemResource(file);
BeanFactory beanFactory = new XmlBeanFactory(resource);
(2)Resource resource = new ClassPathResource("classpath.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
• ClassPathXmlApplicationContext:ApplicationContext实现,从classpath获取配置文件;
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath.xml");
• FileSystemXmlApplicationContext:ApplicationContext实现,从文件系统获取配置文件。
BeanFactory beanFactory = new FileSystemXmlApplicationContext("fileSystemConfig.xml");
小结:
除了测试程序的代码外,也就是程序入口,所有代码都没有出现Spring任何组件,而且所有我们写的代码没有实现框架拥有的接口,因而能非常容易的替换掉Spring,非入侵。
客户端代码完全面向接口编程,无需知道实现类,可以通过修改配置文件来更换接口实现,客户端代码不需要任何修改。低耦合。
如果在开发初期没有真正的实现,我们可以模拟一个实现来测试,不耦合代码,很方便测试。
Bean之间几乎没有依赖关系,很容易重用。
Bean配置相关:
Bean命名:
1. xml里面bean不写id 只写class 对应default-autowire=byType,客户端必须通过接口“T getBean(Class<T> requiredType)”获取Bean;
<bean class=” cn.javass.spring.chapter2.helloworld.HelloImpl”/>
@Test
public void test1() {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("chapter2/namingbean1.xml");
//根据类型获取bean
HelloApi helloApi = beanFactory.getBean(HelloApi.class);
helloApi.sayHello();
}
2. 指定唯一id=“bean”
@Test
public void test2() {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("chapter2/namingbean2.xml");
//根据id获取bean
HelloApi bean = beanFactory.getBean("bean", HelloApi.class);
bean.sayHello();
}
3. 指定唯一name=“bean” @Test内代码同上
4. xml里面 name 和 id 都有写,那么id是标识符,name是别名
<bean id=”bean1”name=”alias1” class=” cn.javass.spring.chapter2.helloworld.HelloImpl”/>
<!-- 如果id和name一样,IoC容器能检测到,并消除冲突 -->
<bean id="bean3" name="bean3" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/>
@Test
public void test4() {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("chapter2/namingbean4.xml");
//根据id获取bean
HelloApi bean1 = beanFactory.getBean("bean1", HelloApi.class);
bean1.sayHello();
//根据别名获取bean
HelloApi bean2 = beanFactory.getBean("alias1", HelloApi.class);
bean2.sayHello();
//根据id获取bean
HelloApi bean3 = beanFactory.getBean("bean3", HelloApi.class);
bean3.sayHello();
String[] bean3Alias = beanFactory.getAliases("bean3");
//因此别名不能和id一样,如果一样则由IoC容器负责消除冲突
Assert.assertEquals(0, bean3Alias.length);
}
5. 指定多个name,多个name用“,”、“;”、“ ”分割,第一个被用作标识符,其他的(alias1、alias2、alias3)是别名,所有标识符也必须在Ioc容器中唯一;
<bean name=” bean1;alias11,alias12;alias13 alias14” class=” cn.javass.spring.chapter2.helloworld.HelloImpl”/>
<!-- 当指定id时,name指定的标识符全部为别名 -->
<bean id="bean2" name="alias21;alias22" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/>
@Test
public void test5() {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("chapter2/namingbean5.xml");
//1根据id获取bean
HelloApi bean1 = beanFactory.getBean("bean1", HelloApi.class);
bean1.sayHello();
//2根据别名获取bean
HelloApi alias11 = beanFactory.getBean("alias11", HelloApi.class);
alias11.sayHello();
//3验证确实是四个别名
String[] bean1Alias = beanFactory.getAliases("bean1");
System.out.println("=======namingbean5.xml bean1 别名========");
for(String alias : bean1Alias) {
System.out.println(alias);
}
Assert.assertEquals(4, bean1Alias.length);
//根据id获取bean
HelloApi bean2 = beanFactory.getBean("bean2", HelloApi.class);
bean2.sayHello();
//2根据别名获取bean
HelloApi alias21 = beanFactory.getBean("alias21", HelloApi.class);
alias21.sayHello();
//验证确实是两个别名
String[] bean2Alias = beanFactory.getAliases("bean2");
System.out.println("=======namingbean5.xml bean2 别名========");
for(String alias : bean2Alias) {
System.out.println(alias);
}
Assert.assertEquals(2, bean2Alias.length);
}
6. 指定了唯一别名alias
<bean name="bean" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/>
<alias alias="alias1" name="bean"/>
<alias alias="alias2" name="bean"/>
@Test
public void test6() {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("chapter2/namingbean6.xml");
//根据id获取bean
HelloApi bean = beanFactory.getBean("bean", HelloApi.class);
bean.sayHello(); //根据别名获取bean
HelloApi alias1 = beanFactory.getBean("alias1", HelloApi.class);
alias1.sayHello();
HelloApi alias2 = beanFactory.getBean("alias2", HelloApi.class);
alias2.sayHello();
String[] beanAlias = beanFactory.getAliases("bean");
System.out.println("=======namingbean6.xml bean 别名========");
for(String alias : beanAlias) {
System.out.println(alias);
}
System.out.println("=======namingbean6.xml bean 别名========");
Assert.assertEquals(2, beanAlias.length);
}
注:从定义来看,name或id如果仅仅指定它们中的一个时会作为“标识符”。而id和name同时存在时呢?这是因为当使用基于XML的配置元数据时,在XML中id是一个真正的XML id属性,因此当其他的定义来引用这个id时就体现出id的好处了,可以利用XML解析器来验证引用的这个id是否存在,从而更早的发现是否引用了一个不存在的bean,而使用name,则可能要在真正使用bean时才能发现引用一个不存在的bean。
Bean实例化:
1. 构造器 constructor-arg
2. 设值 properties
3. 使用静态工厂方式实例化Bean,使用这种方式除了指定必须的class属性,还要指定factory-method属性来指定实例化Bean的方法,而且使用静态工厂方法也允许指定方法参数,spring IoC容器将调用此属性指定的方法来获取Bean。
静态工厂类代码:
public class HelloApiStaticFactory {
//工厂方法
public static HelloApi newInstance(String message) {
//返回需要的Bean实例
return new HelloImpl2(message);
}
}
xml:<!-- 使用静态工厂方法 -->
<bean id="bean3" class="cn.javass.spring.chapter2.HelloApiStaticFactory" factory-method="newInstance">
<constructor-arg index="0" value="Hello Spring!"/>
</bean>
@Test
public void testInstantiatingBeanByStaticFactory() {
//使用静态工厂方法
BeanFactory beanFactory = new ClassPathXmlApplicationContext("chaper2/instantiatingBean.xml");
HelloApi bean3 = beanFactory.getBean("bean3", HelloApi.class);
bean3.sayHello();
}
4. 使用实例工厂方法实例化Bean,使用这种方式不能指定class属性,此时必须使用factory-bean属性来指定工厂Bean,factory-method属性指定实例化Bean的方法,而且使用实例工厂方法允许指定方法参数,方式和使用构造器方式一样。
实例工厂类:
package cn.javass.spring.chapter2;
public class HelloApiInstanceFactory {
public HelloApi newInstance(String message) {
return new HelloImpl2(message);
}
}
xml:
<!—1、定义实例工厂Bean -->
<bean id="beanInstanceFactory" class="cn.javass.spring.chapter2.HelloApiInstanceFactory"/>
<!—2、使用实例工厂Bean创建Bean -->
<bean id="bean4" factory-bean="beanInstanceFactory" factory-method="newInstance">
<constructor-arg index="0" value="Hello Spring!"></constructor-arg>
</bean>
@Test
public void testInstantiatingBeanByInstanceFactory() {
//使用实例工厂方法
BeanFactory beanFactory = new ClassPathXmlApplicationContext("chapter2/instantiatingBean.xml");
HelloApi bean4 = beanFactory.getBean("bean4", HelloApi.class);
bean4.sayHello();
}
到到目前为止,我们只能通过简单的实例化Bean,没有涉及Bean之间关系。接下来一章让我们进入配置Bean之间关系章节,也就是依赖注入。
Spring教程笔记(3)的更多相关文章
- Spring教程笔记(3) Bean
Bean配置项 id class必须项 如果根据id来获取bean,要写id:如果根据类型来配置bean,只写class就可以. scope作用域 constructor arguments prop ...
- Spring教程笔记(2) IOC
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合.更优良的程序. 在Java开发中,Ioc意 ...
- spring入门教程——笔记
Spring学习笔记(1)----简单的实例 --------------------------------- 首先需要准备Spring包,可从官方网站上下载. 下载解压后,必须的两个包是s ...
- Spring教程:tutorialspoint-spring
来自turorialspoint的Spring教程(英文),官网:https://www.tutorialspoint.com/spring/index.htm 这个教程在国内已经被翻译成中文(不过是 ...
- Java系列教程-Spring 教程目录
Spring 教程目录 可参考MyBatis的官方文档也比较清楚 https://mybatis.org/mybatis-3/zh/getting-started.html 代码 目录 https:/ ...
- Spring Security笔记:HTTP Basic 认证
在第一节 Spring Security笔记:Hello World 的基础上,只要把Spring-Security.xml里改一个位置 <http auto-config="true ...
- jQuery官方基础教程笔记(转载)
本文转载于阮一峰的博文,内容基础,结构清晰,是jquery入门不可多得的资料,非常好,赞一个. 阮一峰:jQuery官方基础教程笔记 jQuery是目前使用最广泛的javascript函数库. 据统计 ...
- 【Spring学习笔记-MVC-3.1】SpringMVC返回Json数据-方式1-扩展
<Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...
- (转) Spring读书笔记-----Spring的Bean之配置依赖
前一篇博客介绍了Spring中的Bean的基本概念和作用域(Spring读书笔记-----Spring的Bean之Bean的基本概念),现在介绍Spring Bean的基本配置. 从开始我们知道Jav ...
随机推荐
- es7,es8
ES7新特性 ES7在ES6的基础上添加了三项内容:求幂运算符(**).Array.prototype.includes()方法.函数作用域中严格模式的变更. Array.prototype.incl ...
- 关于weblogic部署Java项目的包冲突问题
我们可能会用各种应用服务部署我们的Java应用,比如Tomcat.WAS.weblogic等.Tomcat和WAS可能会比较少遇到一些奇怪的问题,但是用weblogic部署项目则经常遇到一些比如包冲突 ...
- httplib和urllib2常用方法
都是几年前用过的,现在翻出来记录一下. import httplib import urllib2 import socket ##---------------------------------- ...
- 【题解】Luogu P4436 [HNOI/AHOI2018]游戏
原题传送门 \(n^2\)过百万在HNOI/AHOI2018中真的成功了qwqwq 先将没门分格的地方连起来,枚举每一个块,看向左向右最多能走多远,最坏复杂度\(O(n^2)\),但出题人竟然没卡(建 ...
- Linux驱动
1 驱动分类 常规分类:字符设备.块设备.网络设备 字符设备:一种按字节来访问的设备,字符驱动负责驱动字符设备,这样的驱动通常实现open.close.read和write系统调用.如串口.LED.按 ...
- cf C题
题意:矩阵只包含0,1两种数字,给你一个矩阵A,另一个矩阵B,每一次可以从A中选出一个子矩阵,点击一次使得这个子矩阵的四个角的数字变成与原来相反的数,0变1,1变0.问你可不可以经过有限次的变换把矩阵 ...
- flutter插件汇总2
作者:知乎用户链接:https://www.zhihu.com/question/307594373/answer/568969429来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...
- snmp模拟器snmpsid使用
snmpsim使用 安装 pip install snmpsim 简单使用 生成snmpwalk文件: snmpwalk -v2c -c 'password' -ObentU 218.200.x.15 ...
- scala链接mysql
方法一:链接并操作mysql //链接Mysqlval driver = "com.mysql.jdbc.Driver"val url = "jdbc:mysql://1 ...
- 一梦江湖费六年——QQ群聊天分析
本文结构: 一.那些年我们加过的QQ群 二.数据读入和整理(一)--来自蓝翔的挖掘机 二.数据读入和整理(二)--你不知道的事 三.聊天宏观(1)--寤寐思服 三.聊天宏观(2)日月篇 三.聊天宏观( ...