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 ...
随机推荐
- 单片机C语言基础编程源码六则
1.某单片机系统的P2口接一数模转换器DAC0832输出模拟量,现在要求从DAC0832输出连续的三角波,实现的方法是从P2口连续输出按照三角波变化的数值,从0开始逐渐增大,到某一最大值后逐渐减小,直 ...
- ajax的网上解析
/* 用XMLHTTPRequest来进行ajax异步数据交交互*/ 主要有几个步骤: //1.创建XMLHTTPRequest对象 //最复杂的一步 if (window.XMLHttpReques ...
- 叮咚,你的Lauce上线了!
哈,2014 - 2016 - 2018,虽然每隔两年才有那么一篇随笔,博客园,我还是爱你的~ 嗯,2018,马上又要失业了,我这是自带黑属性啊啊啊哈,工作了4年多的项目要被砍掉了, 倒不是说非要这个 ...
- MTK 使用iptable 命令来完成网络路由(android WIFI/4G分享网络)
很多时候,总有些奇怪的需求,这时候是发挥我们的聪明才智的时候!! 有客户的需求是: 公网 WIFI 4G/其他网络 以太网1 以太网2 内部设备 描述下需求:现今有一个控制设备,里面有WIFI,物联网 ...
- 编译原理 #03# 龙书中缀转后缀JS实现版
// 来自龙书第2章2.5小节-简单表达式的翻译器 笔记 既然是语法制导翻译(Syntax-directed translation),那么最重要的东西当然是描述该语言语法的文法,以下为中缀表达式文法 ...
- RHCE
RHCE 配置 配置firewalld防火墙 配置firewalld端口转发 自定义用户环境 配置链路聚合 配置IPV6地址 配置本地邮件服务
- sql的优化
适当的索引 尽量不要有空判断的语句 尽量不要使用不等于条件 尽量不要使用or条件 尽量不要使用左右模糊查询 尽量使用exists代替in 尽量避免一次性返回大数据量
- es6中promise实现ajax的例子
function getData(url){ var pro = new Promise(function(resolve,reject){ var xhr = null; try{ xhr = ne ...
- 0x16 Tire
参考链接:https://www.cnblogs.com/TheRoadToTheGold/p/6290732.html 题目链接:https://www.acwing.com/problem/con ...
- tcp config
$ sudo sysctl net.ipv4.tcp_reordering=1 $ sudo sysctl net.ipv4.tcp_thin_linear_timeouts=1 $ sudo sys ...